From 86e47c87d560409b9185523a5b6d7f7445570008 Mon Sep 17 00:00:00 2001
From: kiip1 <25848425+kiip1@users.noreply.github.com>
Date: Sat, 28 Jan 2023 21:44:26 +0100
Subject: [PATCH 1/3] Cleanup
---
.../java/ch/njol/yggdrasil/ClassResolver.java | 11 +-
.../DefaultYggdrasilInputStream.java | 125 +++----
.../DefaultYggdrasilOutputStream.java | 154 ++++----
.../java/ch/njol/yggdrasil/FieldHandler.java | 22 +-
src/main/java/ch/njol/yggdrasil/Fields.java | 296 ++++++++-------
.../java/ch/njol/yggdrasil/JRESerializer.java | 104 +++---
.../java/ch/njol/yggdrasil/PseudoEnum.java | 88 +++--
.../njol/yggdrasil/SimpleClassResolver.java | 23 +-
src/main/java/ch/njol/yggdrasil/Tag.java | 71 ++--
.../java/ch/njol/yggdrasil/Yggdrasil.java | 309 +++++++---------
.../ch/njol/yggdrasil/YggdrasilException.java | 14 +-
.../java/ch/njol/yggdrasil/YggdrasilID.java | 4 +-
.../njol/yggdrasil/YggdrasilInputStream.java | 201 ++++-------
.../njol/yggdrasil/YggdrasilOutputStream.java | 205 +++++------
.../njol/yggdrasil/YggdrasilSerializable.java | 64 ++--
.../njol/yggdrasil/YggdrasilSerializer.java | 49 ++-
.../njol/yggdrasil/util/JREFieldHandler.java | 99 +++--
.../njol/yggdrasil/xml/YggXMLInputStream.java | 322 -----------------
.../yggdrasil/xml/YggXMLOutputStream.java | 339 ------------------
.../ch/njol/yggdrasil/xml/package-info.java | 27 --
20 files changed, 815 insertions(+), 1712 deletions(-)
delete mode 100644 src/main/java/ch/njol/yggdrasil/xml/YggXMLInputStream.java
delete mode 100644 src/main/java/ch/njol/yggdrasil/xml/YggXMLOutputStream.java
delete mode 100644 src/main/java/ch/njol/yggdrasil/xml/package-info.java
diff --git a/src/main/java/ch/njol/yggdrasil/ClassResolver.java b/src/main/java/ch/njol/yggdrasil/ClassResolver.java
index bf0c22e29ed..e8cea60120e 100644
--- a/src/main/java/ch/njol/yggdrasil/ClassResolver.java
+++ b/src/main/java/ch/njol/yggdrasil/ClassResolver.java
@@ -29,17 +29,16 @@ public interface ClassResolver {
* @return The Class object that represents data with the given ID, or null if the ID does not belong to the implementor
*/
@Nullable
- public Class> getClass(String id);
+ Class> getClass(String id);
/**
- * Gets an ID for a Class. The ID is used to identify the type of a saved object.
+ * Gets an ID for a Class. The ID is used to identify the type of saved object.
*
- * // TODO make sure that it's unique
- *
- * @param c The class to get the ID of
+ * @param clazz The class to get the ID of
* @return The ID of the given class, or null if this is not a class of the implementor
*/
+ // TODO make sure that it's unique
@Nullable
- public String getID(Class> c);
+ String getID(Class> clazz);
}
diff --git a/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilInputStream.java b/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilInputStream.java
index 2bf434bf364..c2043c3e310 100644
--- a/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilInputStream.java
+++ b/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilInputStream.java
@@ -18,102 +18,89 @@
*/
package ch.njol.yggdrasil;
-import static ch.njol.yggdrasil.Tag.T_ARRAY;
-import static ch.njol.yggdrasil.Tag.T_REFERENCE;
-
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.StreamCorruptedException;
import java.lang.reflect.Array;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-import org.eclipse.jdt.annotation.NonNull;
+import static ch.njol.yggdrasil.Tag.T_ARRAY;
+import static ch.njol.yggdrasil.Tag.T_REFERENCE;
//Naming conventions:
// x(): read info & data (e.g. content type, contents) [i.e. no tag]
// _x(): read data only (e.g. contents)
-
public final class DefaultYggdrasilInputStream extends YggdrasilInputStream {
- @SuppressWarnings("null")
- private final static Charset UTF_8 = Charset.forName("UTF-8");
-
+ private final InputStream in;
private final short version;
- final InputStream in;
-
- public DefaultYggdrasilInputStream(final Yggdrasil y, final InputStream in) throws IOException {
- super(y);
+ public DefaultYggdrasilInputStream(Yggdrasil yggdrasil, InputStream in) throws IOException {
+ super(yggdrasil);
this.in = in;
- final int m = readInt();
- if (m != Yggdrasil.MAGIC_NUMBER)
+ if (readInt() != Yggdrasil.MAGIC_NUMBER)
throw new StreamCorruptedException("Not an Yggdrasil stream");
version = readShort();
if (version <= 0 || version > Yggdrasil.LATEST_VERSION)
throw new StreamCorruptedException("Input was saved using a later version of Yggdrasil");
}
- // private
-
/**
* @throws EOFException If the end of the stream is reached
*/
private int read() throws IOException {
- final int b = in.read();
+ int b = in.read();
if (b < 0)
throw new EOFException();
return b;
}
- private void readFully(final byte[] buf) throws IOException {
- readFully(buf, 0, buf.length);
+ private void readFully(byte[] buf) throws IOException {
+ readFully(buf, buf.length);
}
- private void readFully(final byte[] buf, int off, final int len) throws IOException {
- int l = len;
- while (l > 0) {
- final int n = in.read(buf, off, l);
+ private void readFully(byte[] buf, int startLength) throws IOException {
+ int offset = 0;
+ int length = startLength;
+ while (length > 0) {
+ int n = in.read(buf, offset, length);
if (n < 0)
- throw new EOFException("Expected " + len + " bytes, but could only read " + (len - l));
- off += n;
- l -= n;
+ throw new EOFException("Expected " + startLength + " bytes, but could only read " + (startLength - length));
+ offset += n;
+ length -= n;
}
}
private final List readShortStrings = new ArrayList<>();
private String readShortString() throws IOException {
- final int length = read();
+ int length = read();
if (length == (T_REFERENCE.tag & 0xFF)) {
- final int i = version <= 1 ? readInt() : readUnsignedInt();
+ int i = version <= 1 ? readInt() : readUnsignedInt();
if (i < 0 || i > readShortStrings.size())
throw new StreamCorruptedException("Invalid short string reference " + i);
return "" + readShortStrings.get(i);
}
- final byte[] d = new byte[length];
+ byte[] d = new byte[length];
readFully(d);
- final String s = new String(d, UTF_8);
+ String s = new String(d, StandardCharsets.UTF_8);
if (length > 4)
readShortStrings.add(s);
return s;
}
- // Tag
-
@Override
protected Tag readTag() throws IOException {
- final int t = read();
- final Tag tag = Tag.byID(t);
+ int t = read();
+ Tag tag = Tag.byID(t);
if (tag == null)
throw new StreamCorruptedException("Invalid tag 0x" + Integer.toHexString(t));
return tag;
}
- // Primitives
-
private byte readByte() throws IOException {
return (byte) read();
}
@@ -123,7 +110,7 @@ private short readShort() throws IOException {
}
private short readUnsignedShort() throws IOException {
- final int b = read();
+ int b = read();
if ((b & 0x80) != 0)
return (short) (b & ~0x80);
return (short) (b << 8 | read());
@@ -137,21 +124,17 @@ private int readInt() throws IOException {
}
private int readUnsignedInt() throws IOException {
- final int b = read();
+ int b = read();
if ((b & 0x80) != 0)
return (b & ~0x80) << 8 | read();
return b << 24 | read() << 16 | read() << 8 | read();
}
private long readLong() throws IOException {
- return (long) read() << 56
- | (long) read() << 48
- | (long) read() << 40
- | (long) read() << 32
- | (long) read() << 24
- | read() << 16
- | read() << 8
- | read();
+ return (long) read() << 56 | (long) read() << 48
+ | (long) read() << 40 | (long) read() << 32
+ | (long) read() << 24 | (long) read() << 16
+ | (long) read() << 8 | read();
}
private float readFloat() throws IOException {
@@ -167,7 +150,7 @@ private char readChar() throws IOException {
}
private boolean readBoolean() throws IOException {
- final int r = read();
+ int r = read();
if (r == 0)
return false;
else if (r == 1)
@@ -176,7 +159,7 @@ else if (r == 1)
}
@Override
- protected Object readPrimitive(final Tag type) throws IOException {
+ protected Object readPrimitive(Tag type) throws IOException {
switch (type) {
case T_BYTE:
return readByte();
@@ -194,29 +177,24 @@ protected Object readPrimitive(final Tag type) throws IOException {
return readChar();
case T_BOOLEAN:
return readBoolean();
- //$CASES-OMITTED$
default:
throw new YggdrasilException("Internal error; " + type);
}
}
@Override
- protected Object readPrimitive_(final Tag type) throws IOException {
+ protected Object readPrimitive_(Tag type) throws IOException {
return readPrimitive(type);
}
- // String
-
@Override
protected String readString() throws IOException {
- final int length = readUnsignedInt();
- final byte[] d = new byte[length];
+ int length = readUnsignedInt();
+ byte[] d = new byte[length];
readFully(d);
- return new String(d, UTF_8);
+ return new String(d, StandardCharsets.UTF_8);
}
- // Array
-
@Override
protected Class> readArrayComponentType() throws IOException {
return readClass();
@@ -227,8 +205,6 @@ protected int readArrayLength() throws IOException {
return readUnsignedInt();
}
- // Enum
-
@Override
protected Class> readEnumType() throws IOException {
return yggdrasil.getClass(readShortString());
@@ -239,21 +215,18 @@ protected String readEnumID() throws IOException {
return readShortString();
}
- // Class
-
@SuppressWarnings("null")
@Override
protected Class> readClass() throws IOException {
Tag type;
- int dim = 0;
+ int dimensions = 0;
while ((type = readTag()) == T_ARRAY)
- dim++;
- @NonNull
- Class> c;
+ dimensions++;
+ Class> clazz;
switch (type) {
case T_OBJECT:
case T_ENUM:
- c = yggdrasil.getClass(readShortString());
+ clazz = yggdrasil.getClass(readShortString());
break;
case T_BOOLEAN:
case T_BOOLEAN_OBJ:
@@ -273,8 +246,8 @@ protected Class> readClass() throws IOException {
case T_SHORT_OBJ:
case T_CLASS:
case T_STRING:
- c = type.c;
- assert c != null;
+ assert type.type != null;
+ clazz = type.type;
break;
case T_NULL:
case T_REFERENCE:
@@ -283,20 +256,16 @@ protected Class> readClass() throws IOException {
default:
throw new YggdrasilException("Internal error; " + type);
}
- while (dim-- > 0)
- c = Array.newInstance(c, 0).getClass();
- return c;
+ while (dimensions-- > 0)
+ clazz = Array.newInstance(clazz, 0).getClass();
+ return clazz;
}
- // Reference
-
@Override
protected int readReference() throws IOException {
return readUnsignedInt();
}
- // generic Object
-
@Override
protected Class> readObjectType() throws IOException {
return yggdrasil.getClass(readShortString());
@@ -312,14 +281,12 @@ protected String readFieldID() throws IOException {
return readShortString();
}
- // stream
-
@Override
public void close() throws IOException {
try {
read();
throw new StreamCorruptedException("Stream still has data, at least " + (1 + in.available()) + " bytes remain");
- } catch (final EOFException e) {} finally {
+ } catch (EOFException ignored) {} finally {
in.close();
}
}
diff --git a/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilOutputStream.java b/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilOutputStream.java
index 139a50b6e00..f77b8c2405c 100644
--- a/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilOutputStream.java
+++ b/src/main/java/ch/njol/yggdrasil/DefaultYggdrasilOutputStream.java
@@ -18,81 +18,75 @@
*/
package ch.njol.yggdrasil;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+
import static ch.njol.yggdrasil.Tag.T_ARRAY;
import static ch.njol.yggdrasil.Tag.T_REFERENCE;
import static ch.njol.yggdrasil.Tag.getPrimitiveFromWrapper;
import static ch.njol.yggdrasil.Tag.getType;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.nio.charset.Charset;
-import java.util.HashMap;
-
public final class DefaultYggdrasilOutputStream extends YggdrasilOutputStream {
- private final static Charset UTF_8 = Charset.forName("UTF-8");
-
private final OutputStream out;
-
private final short version;
- public DefaultYggdrasilOutputStream(final Yggdrasil y, final OutputStream out) throws IOException {
- super(y);
+ public DefaultYggdrasilOutputStream(Yggdrasil yggdrasil, OutputStream out) throws IOException {
+ super(yggdrasil);
this.out = out;
- version = y.version;
+ version = yggdrasil.version;
writeInt(Yggdrasil.MAGIC_NUMBER);
writeShort(version);
}
- // private
-
- private void write(final int b) throws IOException {
+ private void write(int b) throws IOException {
out.write(b);
}
@Override
- protected void writeTag(final Tag t) throws IOException {
- out.write(t.tag);
+ protected void writeTag(Tag tag) throws IOException {
+ out.write(tag.tag);
}
- private final HashMap writtenShortStrings = new HashMap<>();
+ private final Map writtenShortStrings = new HashMap<>();
int nextShortStringID = 0;
/**
* Writes a class ID or Field name
*/
- private void writeShortString(final String s) throws IOException {
- if (writtenShortStrings.containsKey(s)) {
+ private void writeShortString(String string) throws IOException {
+ if (writtenShortStrings.containsKey(string)) {
writeTag(T_REFERENCE);
if (version <= 1)
- writeInt(writtenShortStrings.get(s));
+ writeInt(writtenShortStrings.get(string));
else
- writeUnsignedInt(writtenShortStrings.get(s));
+ writeUnsignedInt(writtenShortStrings.get(string));
} else {
if (nextShortStringID < 0)
throw new YggdrasilException("Too many field names/class IDs (max: " + Integer.MAX_VALUE + ")");
- final byte[] d = s.getBytes(UTF_8);
+ byte[] d = string.getBytes(StandardCharsets.UTF_8);
if (d.length >= (T_REFERENCE.tag & 0xFF))
- throw new YggdrasilException("Field name or Class ID too long: " + s);
+ throw new YggdrasilException("Field name or Class ID too long: " + string);
write(d.length);
out.write(d);
if (d.length > 4)
- writtenShortStrings.put(s, nextShortStringID++);
+ writtenShortStrings.put(string, nextShortStringID++);
}
}
- // Primitives
-
- private void writeByte(final byte b) throws IOException {
+ private void writeByte(byte b) throws IOException {
write(b & 0xFF);
}
- private void writeShort(final short s) throws IOException {
+ private void writeShort(short s) throws IOException {
write((s >>> 8) & 0xFF);
write(s & 0xFF);
}
- private void writeUnsignedShort(final short s) throws IOException {
+ private void writeUnsignedShort(short s) throws IOException {
assert s >= 0;
if (s <= 0x7f)
writeByte((byte) (0x80 | s));
@@ -100,14 +94,14 @@ private void writeUnsignedShort(final short s) throws IOException {
writeShort(s);
}
- private void writeInt(final int i) throws IOException {
+ private void writeInt(int i) throws IOException {
write((i >>> 24) & 0xFF);
write((i >>> 16) & 0xFF);
write((i >>> 8) & 0xFF);
write(i & 0xFF);
}
- private void writeUnsignedInt(final int i) throws IOException {
+ private void writeUnsignedInt(int i) throws IOException {
assert i >= 0;
if (i <= 0x7FFF)
writeShort((short) (0x8000 | i));
@@ -115,7 +109,7 @@ private void writeUnsignedInt(final int i) throws IOException {
writeInt(i);
}
- private void writeLong(final long l) throws IOException {
+ private void writeLong(long l) throws IOException {
write((int) ((l >>> 56) & 0xFF));
write((int) ((l >>> 48) & 0xFF));
write((int) ((l >>> 40) & 0xFF));
@@ -126,102 +120,96 @@ private void writeLong(final long l) throws IOException {
write((int) (l & 0xFF));
}
- private void writeFloat(final float f) throws IOException {
+ private void writeFloat(float f) throws IOException {
writeInt(Float.floatToIntBits(f));
}
- private void writeDouble(final double d) throws IOException {
+ private void writeDouble(double d) throws IOException {
writeLong(Double.doubleToLongBits(d));
}
- private void writeChar(final char c) throws IOException {
+ private void writeChar(char c) throws IOException {
writeShort((short) c);
}
- private void writeBoolean(final boolean b) throws IOException {
+ private void writeBoolean(boolean b) throws IOException {
write(b ? 1 : 0);
}
@Override
- protected void writePrimitive_(final Object o) throws IOException {
- switch (getPrimitiveFromWrapper(o.getClass())) {
+ protected void writePrimitive_(Object object) throws IOException {
+ switch (getPrimitiveFromWrapper(object.getClass())) {
case T_BYTE:
- writeByte((Byte) o);
+ writeByte((Byte) object);
break;
case T_SHORT:
- writeShort((Short) o);
+ writeShort((Short) object);
break;
case T_INT:
- writeInt((Integer) o);
+ writeInt((Integer) object);
break;
case T_LONG:
- writeLong((Long) o);
+ writeLong((Long) object);
break;
case T_FLOAT:
- writeFloat((Float) o);
+ writeFloat((Float) object);
break;
case T_DOUBLE:
- writeDouble((Double) o);
+ writeDouble((Double) object);
break;
case T_CHAR:
- writeChar((Character) o);
+ writeChar((Character) object);
break;
case T_BOOLEAN:
- writeBoolean((Boolean) o);
+ writeBoolean((Boolean) object);
break;
//$CASES-OMITTED$
default:
- throw new YggdrasilException("Invalid call to writePrimitive with argument " + o);
+ throw new YggdrasilException("Invalid call to writePrimitive with argument " + object);
}
}
@Override
- protected void writePrimitiveValue(final Object o) throws IOException {
- writePrimitive_(o);
+ protected void writePrimitiveValue(Object object) throws IOException {
+ writePrimitive_(object);
}
- // String
-
@Override
- protected void writeStringValue(final String s) throws IOException {
- final byte[] d = s.getBytes(UTF_8);
+ protected void writeStringValue(String string) throws IOException {
+ byte[] d = string.getBytes(StandardCharsets.UTF_8);
writeUnsignedInt(d.length);
out.write(d);
}
- // Array
-
@Override
- protected void writeArrayComponentType(final Class> componentType) throws IOException {
+ protected void writeArrayComponentType(Class> componentType) throws IOException {
writeClass_(componentType);
}
@Override
- protected void writeArrayLength(final int length) throws IOException {
+ protected void writeArrayLength(int length) throws IOException {
writeUnsignedInt(length);
}
@Override
- protected void writeArrayEnd() throws IOException {}
-
- // Class
+ protected void writeArrayEnd() {}
@Override
- protected void writeClassType(final Class> c) throws IOException {
- writeClass_(c);
+ protected void writeClassType(Class> type) throws IOException {
+ writeClass_(type);
}
- private void writeClass_(Class> c) throws IOException {
- while (c.isArray()) {
+ private void writeClass_(Class> type) throws IOException {
+ while (type.isArray()) {
writeTag(T_ARRAY);
- c = c.getComponentType();
+ type = type.getComponentType();
}
- final Tag t = getType(c);
- switch (t) {
+ Tag tag = getType(type);
+ switch (tag) {
case T_OBJECT:
case T_ENUM:
- writeTag(t);
- writeShortString(yggdrasil.getID(c));
+ writeTag(tag);
+ writeShortString(yggdrasil.getID(type));
break;
case T_BOOLEAN:
case T_BOOLEAN_OBJ:
@@ -241,57 +229,49 @@ private void writeClass_(Class> c) throws IOException {
case T_SHORT_OBJ:
case T_CLASS:
case T_STRING:
- writeTag(t);
+ writeTag(tag);
break;
case T_NULL:
case T_REFERENCE:
case T_ARRAY:
default:
- throw new YggdrasilException("" + c.getCanonicalName());
+ throw new YggdrasilException("" + type.getCanonicalName());
}
}
- // Enum
-
@Override
- protected void writeEnumType(final String type) throws IOException {
+ protected void writeEnumType(String type) throws IOException {
writeShortString(type);
}
@Override
- protected void writeEnumID(final String id) throws IOException {
+ protected void writeEnumID(String id) throws IOException {
writeShortString(id);
}
- // generic Object
-
@Override
- protected void writeObjectType(final String type) throws IOException {
+ protected void writeObjectType(String type) throws IOException {
writeShortString(type);
}
@Override
- protected void writeNumFields(final short numFields) throws IOException {
+ protected void writeNumFields(short numFields) throws IOException {
writeUnsignedShort(numFields);
}
@Override
- protected void writeFieldID(final String id) throws IOException {
+ protected void writeFieldID(String id) throws IOException {
writeShortString(id);
}
@Override
- protected void writeObjectEnd() throws IOException {}
-
- // Reference
+ protected void writeObjectEnd() {}
@Override
- protected void writeReferenceID(final int ref) throws IOException {
- writeUnsignedInt(ref);
+ protected void writeReferenceID(int reference) throws IOException {
+ writeUnsignedInt(reference);
}
- // stream
-
@Override
public void flush() throws IOException {
out.flush();
diff --git a/src/main/java/ch/njol/yggdrasil/FieldHandler.java b/src/main/java/ch/njol/yggdrasil/FieldHandler.java
index c912924ff9f..ea894c68088 100644
--- a/src/main/java/ch/njol/yggdrasil/FieldHandler.java
+++ b/src/main/java/ch/njol/yggdrasil/FieldHandler.java
@@ -18,39 +18,39 @@
*/
package ch.njol.yggdrasil;
+import ch.njol.yggdrasil.Fields.FieldContext;
+
import java.io.StreamCorruptedException;
import java.lang.reflect.Field;
-import ch.njol.yggdrasil.Fields.FieldContext;
-
public interface FieldHandler {
/**
* Called when a loaded field doesn't exist.
*
- * @param o The object whose filed is missing
+ * @param object The object whose filed is missing
* @param field The field read from stream
* @return Whether this Handler handled the request
*/
- public boolean excessiveField(Object o, FieldContext field) throws StreamCorruptedException;
+ boolean excessiveField(Object object, FieldContext field) throws StreamCorruptedException;
/**
* Called if a field was not found in the stream.
*
- * @param o The object whose filed is missing
+ * @param object The object whose filed is missing
* @param field The field that didn't occur in the stream
* @return Whether this Handler handled the request
*/
- public boolean missingField(Object o, Field field) throws StreamCorruptedException;
+ boolean missingField(Object object, Field field) throws StreamCorruptedException;
/**
- * Called when a loaded value is not compatible with the type of a field.
+ * Called when a loaded value is not compatible with the type of field.
*
- * @param o The object the field belongs to
- * @param f The field to set
- * @param field The field read from stream
+ * @param object The object the field belongs to
+ * @param field The field to set
+ * @param context The field read from stream
* @return Whether this Handler handled the request
*/
- public boolean incompatibleField(Object o, Field f, FieldContext field) throws StreamCorruptedException;
+ boolean incompatibleField(Object object, Field field, FieldContext context) throws StreamCorruptedException;
}
diff --git a/src/main/java/ch/njol/yggdrasil/Fields.java b/src/main/java/ch/njol/yggdrasil/Fields.java
index 11d8b18fadc..865f3cf2bf3 100644
--- a/src/main/java/ch/njol/yggdrasil/Fields.java
+++ b/src/main/java/ch/njol/yggdrasil/Fields.java
@@ -18,6 +18,11 @@
*/
package ch.njol.yggdrasil;
+import ch.njol.yggdrasil.Fields.FieldContext;
+import ch.njol.yggdrasil.YggdrasilSerializable.YggdrasilRobustSerializable;
+import org.eclipse.jdt.annotation.Nullable;
+
+import javax.annotation.concurrent.NotThreadSafe;
import java.io.NotSerializableException;
import java.io.StreamCorruptedException;
import java.lang.reflect.Field;
@@ -31,40 +36,31 @@
import java.util.Map;
import java.util.Set;
-import javax.annotation.concurrent.NotThreadSafe;
-
-import org.eclipse.jdt.annotation.Nullable;
-
-import ch.njol.yggdrasil.Fields.FieldContext; // required - wtf
-import ch.njol.yggdrasil.YggdrasilSerializable.YggdrasilRobustSerializable;
-
@NotThreadSafe
public final class Fields implements Iterable {
/**
- * Holds a field's name and value, and throws {@link StreamCorruptedException}s if primitives or objects are used incorrectly.
- *
- * @author Peter Güttinger
+ * Holds a field's name and value, and throws {@link StreamCorruptedException}s
+ * if primitives or objects are used incorrectly.
*/
@NotThreadSafe
- public final static class FieldContext {
+ public static final class FieldContext {
final String id;
/** not null if this {@link #isPrimitiveValue is a primitive} */
@Nullable
private Object value;
-
private boolean isPrimitiveValue;
- FieldContext(final String id) {
+ FieldContext(String id) {
this.id = id;
}
- FieldContext(final Field f, final Object o) throws IllegalArgumentException, IllegalAccessException {
- id = Yggdrasil.getID(f);
- value = f.get(o);
- isPrimitiveValue = f.getType().isPrimitive();
+ FieldContext(Field field, Object object) throws IllegalArgumentException, IllegalAccessException {
+ id = Yggdrasil.getID(field);
+ value = field.get(object);
+ isPrimitiveValue = field.getType().isPrimitive();
}
public String getID() {
@@ -77,12 +73,12 @@ public boolean isPrimitive() {
@Nullable
public Class> getType() {
- final Object value = this.value;
+ Object value = this.value;
if (value == null)
return null;
- final Class> c = value.getClass();
- assert c != null;
- return isPrimitiveValue ? Tag.getPrimitiveFromWrapper(c).c : c;
+ Class> type = value.getClass();
+ assert type != null;
+ return isPrimitiveValue ? Tag.getPrimitiveFromWrapper(type).type : type;
}
@Nullable
@@ -94,10 +90,10 @@ public Object getObject() throws StreamCorruptedException {
@SuppressWarnings("unchecked")
@Nullable
- public T getObject(final Class expectedType) throws StreamCorruptedException {
+ public T getObject(Class expectedType) throws StreamCorruptedException {
if (isPrimitiveValue)
throw new StreamCorruptedException("field " + id + " is a primitive, but expected " + expectedType);
- final Object value = this.value;
+ Object value = this.value;
if (value != null && !expectedType.isInstance(value))
throw new StreamCorruptedException("Field " + id + " of " + value.getClass() + ", but expected " + expectedType);
return (T) value;
@@ -111,42 +107,42 @@ public Object getPrimitive() throws StreamCorruptedException {
}
@SuppressWarnings("unchecked")
- public T getPrimitive(final Class expectedType) throws StreamCorruptedException {
+ public T getPrimitive(Class expectedType) throws StreamCorruptedException {
if (!isPrimitiveValue)
throw new StreamCorruptedException("field " + id + " is not a primitive, but expected " + expectedType);
assert expectedType.isPrimitive() || Tag.isWrapper(expectedType);
- final Object value = this.value;
+ Object value = this.value;
assert value != null;
if (!(expectedType.isPrimitive() ? Tag.getWrapperClass(expectedType).isInstance(value) : expectedType.isInstance(value)))
throw new StreamCorruptedException("Field " + id + " of " + value.getClass() + ", but expected " + expectedType);
return (T) value;
}
- public void setObject(final @Nullable Object value) {
+ public void setObject(@Nullable Object value) {
this.value = value;
isPrimitiveValue = false;
}
- public void setPrimitive(final Object value) {
- assert value != null && Tag.isWrapper(value.getClass());
+ public void setPrimitive(Object value) {
+ assert Tag.isWrapper(value.getClass());
this.value = value;
isPrimitiveValue = true;
}
- public void setField(final Object o, final Field f, final Yggdrasil y) throws StreamCorruptedException {
- if (Modifier.isStatic(f.getModifiers()))
- throw new StreamCorruptedException("The field " + id + " of " + f.getDeclaringClass() + " is static");
- if (Modifier.isTransient(f.getModifiers()))
- throw new StreamCorruptedException("The field " + id + " of " + f.getDeclaringClass() + " is transient");
- if (f.getType().isPrimitive() != isPrimitiveValue)
- throw new StreamCorruptedException("The field " + id + " of " + f.getDeclaringClass() + " is " + (f.getType().isPrimitive() ? "" : "not ") + "primitive");
+ public void setField(Object object, Field field, Yggdrasil yggdrasil) throws StreamCorruptedException {
+ if (Modifier.isStatic(field.getModifiers()))
+ throw new StreamCorruptedException("The field " + id + " of " + field.getDeclaringClass() + " is static");
+ if (Modifier.isTransient(field.getModifiers()))
+ throw new StreamCorruptedException("The field " + id + " of " + field.getDeclaringClass() + " is transient");
+ if (field.getType().isPrimitive() != isPrimitiveValue)
+ throw new StreamCorruptedException("The field " + id + " of " + field.getDeclaringClass() + " is " + (field.getType().isPrimitive() ? "" : "not ") + "primitive");
try {
- f.setAccessible(true);
- f.set(o, value);
- } catch (final IllegalArgumentException e) {
- if (!(o instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) o).incompatibleField(f, this))
- y.incompatibleField(o, f, this);
- } catch (final IllegalAccessException e) {
+ field.setAccessible(true);
+ field.set(object, value);
+ } catch (IllegalArgumentException e) {
+ if (!(object instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) object).incompatibleField(field, this))
+ yggdrasil.incompatibleField(object, field, this);
+ } catch (IllegalAccessException e) {
assert false;
}
}
@@ -157,14 +153,14 @@ public int hashCode() {
}
@Override
- public boolean equals(final @Nullable Object obj) {
- if (this == obj)
+ public boolean equals(@Nullable Object object) {
+ if (this == object)
return true;
- if (obj == null)
+ if (object == null)
return false;
- if (!(obj instanceof FieldContext))
+ if (!(object instanceof FieldContext))
return false;
- final FieldContext other = (FieldContext) obj;
+ FieldContext other = (FieldContext) object;
return id.equals(other.id);
}
@@ -182,130 +178,132 @@ public Fields() {
yggdrasil = null;
}
- public Fields(final Yggdrasil yggdrasil) {
+ public Fields(Yggdrasil yggdrasil) {
this.yggdrasil = yggdrasil;
}
/**
- * Creates a fields object and initialises it with all non-transient and non-static fields of the given class and its superclasses.
+ * Creates a fields object and initialises it with all non-transient and
+ * non-static fields of the given class and its superclasses.
*
- * @param c Some class
- * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a field with the same name as a field in one of its superclasses)
+ * @param type Some class
+ * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a
+ * field with the same name as a field in one of its superclasses)
*/
- public Fields(final Class> c, final Yggdrasil yggdrasil) throws NotSerializableException {
+ public Fields(Class> type, Yggdrasil yggdrasil) throws NotSerializableException {
this.yggdrasil = yggdrasil;
- for (final Field f : getFields(c)) {
- assert f != null;
- final String id = Yggdrasil.getID(f);
+ for (Field field : getFields(type)) {
+ assert field != null;
+ String id = Yggdrasil.getID(field);
fields.put(id, new FieldContext(id));
}
}
/**
- * Creates a fields object and initialises it with all non-transient and non-static fields of the given object.
+ * Creates a fields object and initialises it with all non-transient
+ * and non-static fields of the given object.
*
- * @param o Some object
- * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a field with the same name as a field in one of its superclasses)
+ * @param object Some object
+ * @throws NotSerializableException If a field occurs more than once (i.e. if a class
+ * has a field with the same name as a field in one of its superclasses)
*/
- public Fields(final Object o) throws NotSerializableException {
- this(o, null);
+ public Fields(Object object) throws NotSerializableException {
+ this(object, null);
}
/**
- * Creates a fields object and initialises it with all non-transient and non-static fields of the given object.
+ * Creates a fields object and initialises it with all non-transient
+ * and non-static fields of the given object.
*
- * @param o Some object
- * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a field with the same name as a field in one of its superclasses)
+ * @param object Some object
+ * @throws NotSerializableException If a field occurs more than once (i.e. if a class
+ * has a field with the same name as a field in one of its superclasses)
*/
- public Fields(final Object o, @Nullable final Yggdrasil yggdrasil) throws NotSerializableException {
+ public Fields(Object object, @Nullable Yggdrasil yggdrasil) throws NotSerializableException {
this.yggdrasil = yggdrasil;
- final Class> c = o.getClass();
- assert c != null;
- for (final Field f : getFields(c)) {
- assert f != null;
+ Class> type = object.getClass();
+ assert type != null;
+ for (Field field : getFields(type)) {
+ assert field != null;
try {
- fields.put(Yggdrasil.getID(f), new FieldContext(f, o));
- } catch (final IllegalArgumentException e) {
- assert false;
- } catch (final IllegalAccessException e) {
+ fields.put(Yggdrasil.getID(field), new FieldContext(field, object));
+ } catch (IllegalArgumentException | IllegalAccessException e) {
assert false;
}
}
}
- private final static Map, Collection> cache = new HashMap<>();
+ private static final Map, Collection> cache = new HashMap<>();
/**
- * Gets all serialisable fields of the provided class, including superclasses.
+ * Gets all serializable fields of the provided class, including superclasses.
*
- * @param c The class to get the fields of
+ * @param type The class to get the fields of
* @return All non-static and non-transient fields of the given class and its superclasses
- * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a field with the same name as a field in one of its superclasses)
+ * @throws NotSerializableException If a field occurs more than once (i.e. if a class has a
+ * field with the same name as a field in one of its superclasses)
*/
- public static Collection getFields(final Class> c) throws NotSerializableException {
- Collection fields = cache.get(c);
+ public static Collection getFields(Class> type) throws NotSerializableException {
+ Collection fields = cache.get(type);
if (fields != null)
return fields;
fields = new ArrayList<>();
- final Set ids = new HashSet<>();
- for (Class> sc = c; sc != null; sc = sc.getSuperclass()) {
- final Field[] fs = sc.getDeclaredFields();
- for (final Field f : fs) {
- final int m = f.getModifiers();
- if (Modifier.isStatic(m) || Modifier.isTransient(m))
+ Set ids = new HashSet<>();
+ for (Class> superClass = type; superClass != null; superClass = superClass.getSuperclass()) {
+ Field[] declaredFields = superClass.getDeclaredFields();
+ for (Field field : declaredFields) {
+ int modifiers = field.getModifiers();
+ if (Modifier.isStatic(modifiers) || Modifier.isTransient(modifiers))
continue;
- final String id = Yggdrasil.getID(f);
+ String id = Yggdrasil.getID(field);
if (ids.contains(id))
- throw new NotSerializableException(c + "/" + sc + ": duplicate field id '" + id + "'");
- f.setAccessible(true);
- fields.add(f);
+ throw new NotSerializableException(type + "/" + superClass + ": duplicate field id '" + id + "'");
+ field.setAccessible(true);
+ fields.add(field);
ids.add(id);
}
}
fields = Collections.unmodifiableCollection(fields);
- assert fields != null;
- cache.put(c, fields);
+ cache.put(type, fields);
return fields;
}
/**
* Sets all fields of the given Object to the values stored in this Fields object.
*
- * @param o The object whose fields should be set
- * @throws StreamCorruptedException
- * @throws NotSerializableException
+ * @param object The object whose fields should be set
* @throws YggdrasilException If this was called on a Fields object not created by Yggdrasil itself
*/
- public void setFields(final Object o) throws StreamCorruptedException, NotSerializableException {
- final Yggdrasil y = yggdrasil;
- if (y == null)
+ public void setFields(Object object) throws StreamCorruptedException, NotSerializableException {
+ Yggdrasil yggdrasil = this.yggdrasil;
+ if (yggdrasil == null)
throw new YggdrasilException("");
- final Set excessive = new HashSet<>(fields.values());
- final Class> oc = o.getClass();
- assert oc != null;
- for (final Field f : getFields(oc)) {
- assert f != null;
- final String id = Yggdrasil.getID(f);
- final FieldContext c = fields.get(id);
- if (c == null) {
- if (!(o instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) o).missingField(f))
- y.missingField(o, f);
+ Set excessive = new HashSet<>(fields.values());
+ Class> type = object.getClass();
+ assert type != null;
+ for (Field field : getFields(type)) {
+ assert field != null;
+ String id = Yggdrasil.getID(field);
+ FieldContext context = fields.get(id);
+ if (context == null) {
+ if (!(object instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) object).missingField(field))
+ yggdrasil.missingField(object, field);
} else {
- c.setField(o, f, y);
+ context.setField(object, field, yggdrasil);
}
- excessive.remove(c);
+ excessive.remove(context);
}
- for (final FieldContext f : excessive) {
- assert f != null;
- if (!(o instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) o).excessiveField(f))
- y.excessiveField(o, f);
+ for (FieldContext context : excessive) {
+ assert context != null;
+ if (!(object instanceof YggdrasilRobustSerializable) || !((YggdrasilRobustSerializable) object).excessiveField(context))
+ yggdrasil.excessiveField(object, context);
}
}
@Deprecated
- public void setFields(final Object o, final Yggdrasil y) throws StreamCorruptedException, NotSerializableException {
- assert yggdrasil == y;
- setFields(o);
+ public void setFields(Object object, Yggdrasil yggdrasil) throws StreamCorruptedException, NotSerializableException {
+ assert this.yggdrasil == yggdrasil;
+ setFields(object);
}
/**
@@ -315,75 +313,75 @@ public int size() {
return fields.size();
}
- public void putObject(final String fieldID, final @Nullable Object value) {
- FieldContext c = fields.get(fieldID);
- if (c == null)
- fields.put(fieldID, c = new FieldContext(fieldID));
- c.setObject(value);
+ public void putObject(String fieldID, @Nullable Object value) {
+ FieldContext context = fields.get(fieldID);
+ if (context == null)
+ fields.put(fieldID, context = new FieldContext(fieldID));
+ context.setObject(value);
}
- public void putPrimitive(final String fieldID, final Object value) {
- FieldContext c = fields.get(fieldID);
- if (c == null)
- fields.put(fieldID, c = new FieldContext(fieldID));
- c.setPrimitive(value);
+ public void putPrimitive(String fieldID, Object value) {
+ FieldContext context = fields.get(fieldID);
+ if (context == null)
+ fields.put(fieldID, context = new FieldContext(fieldID));
+ context.setPrimitive(value);
}
/**
* @param fieldID A field's id
* @return Whether the field is defined
*/
- public boolean contains(final String fieldID) {
+ public boolean contains(String fieldID) {
return fields.containsKey(fieldID);
}
public boolean hasField(String fieldID) {
- return this.fields.containsKey(fieldID);
+ return fields.containsKey(fieldID);
}
@Nullable
- public Object getObject(final String field) throws StreamCorruptedException {
- final FieldContext c = fields.get(field);
- if (c == null)
+ public Object getObject(String field) throws StreamCorruptedException {
+ FieldContext context = fields.get(field);
+ if (context == null)
throw new StreamCorruptedException("Nonexistent field " + field);
- return c.getObject();
+ return context.getObject();
}
@Nullable
- public T getObject(final String fieldID, final Class expectedType) throws StreamCorruptedException {
+ public T getObject(String fieldID, Class expectedType) throws StreamCorruptedException {
assert !expectedType.isPrimitive();
- final FieldContext c = fields.get(fieldID);
- if (c == null)
+ FieldContext context = fields.get(fieldID);
+ if (context == null)
throw new StreamCorruptedException("Nonexistent field " + fieldID);
- return c.getObject(expectedType);
+ return context.getObject(expectedType);
}
- public Object getPrimitive(final String fieldID) throws StreamCorruptedException {
- final FieldContext c = fields.get(fieldID);
- if (c == null)
+ public Object getPrimitive(String fieldID) throws StreamCorruptedException {
+ FieldContext context = fields.get(fieldID);
+ if (context == null)
throw new StreamCorruptedException("Nonexistent field " + fieldID);
- return c.getPrimitive();
+ return context.getPrimitive();
}
- public T getPrimitive(final String fieldID, final Class expectedType) throws StreamCorruptedException {
+ public T getPrimitive(String fieldID, Class expectedType) throws StreamCorruptedException {
assert expectedType.isPrimitive() || Tag.getPrimitiveFromWrapper(expectedType).isPrimitive();
- final FieldContext c = fields.get(fieldID);
- if (c == null)
+ FieldContext context = fields.get(fieldID);
+ if (context == null)
throw new StreamCorruptedException("Nonexistent field " + fieldID);
- return c.getPrimitive(expectedType);
+ return context.getPrimitive(expectedType);
}
@Nullable
- public T getAndRemoveObject(final String field, final Class expectedType) throws StreamCorruptedException {
- final T t = getObject(field, expectedType);
+ public T getAndRemoveObject(String field, Class expectedType) throws StreamCorruptedException {
+ T object = getObject(field, expectedType);
removeField(field);
- return t;
+ return object;
}
- public T getAndRemovePrimitive(final String field, final Class expectedType) throws StreamCorruptedException {
- final T t = getPrimitive(field, expectedType);
+ public T getAndRemovePrimitive(String field, Class expectedType) throws StreamCorruptedException {
+ T object = getPrimitive(field, expectedType);
removeField(field);
- return t;
+ return object;
}
/**
@@ -392,7 +390,7 @@ public T getAndRemovePrimitive(final String field, final Class expectedTy
* @param fieldID The id of the field to remove
* @return Whether a field with the given name was actually defined
*/
- public boolean removeField(final String fieldID) {
+ public boolean removeField(String fieldID) {
return fields.remove(fieldID) != null;
}
diff --git a/src/main/java/ch/njol/yggdrasil/JRESerializer.java b/src/main/java/ch/njol/yggdrasil/JRESerializer.java
index f08c83831e1..fdd2bfafaaa 100644
--- a/src/main/java/ch/njol/yggdrasil/JRESerializer.java
+++ b/src/main/java/ch/njol/yggdrasil/JRESerializer.java
@@ -18,6 +18,9 @@
*/
package ch.njol.yggdrasil;
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.Nullable;
+
import java.io.NotSerializableException;
import java.io.StreamCorruptedException;
import java.util.ArrayList;
@@ -26,75 +29,68 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.UUID;
-import org.eclipse.jdt.annotation.Nullable;
-
public class JRESerializer extends YggdrasilSerializer