package net.minecraft.server;
import com.google.common.base.Charsets;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.koloboke.collect.map.hash.HashObjObjMaps;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Logger;
import org.torch.api.Async;
import org.torch.server.cache.Caches;
import static org.torch.server.TorchServer.logger;
public class JsonList<K, V extends JsonListEntry<K>> {
protected static final Logger a = logger;
protected final Gson b;
private final File c;
private final Map<String, V> d = HashObjObjMaps.newMutableMap();
private boolean e = true;
private static final ParameterizedType f = new ParameterizedType() {
@Override
public Type[] getActualTypeArguments() {
return new Type[] { JsonListEntry.class};
}
@Override
public Type getRawType() {
return List.class;
}
@Override
public Type getOwnerType() {
return null;
}
};
// Torch start
private final static long EXPIRE_CHECK_INTERVAL = TimeUnit.MILLISECONDS.convert(9, TimeUnit.SECONDS); // TODO: configurable
/** The last time to check expire, in milliseconds. */
private long lastExpireCheckTime = System.currentTimeMillis();
// Torch end
public JsonList(File file) {
this.c = file;
GsonBuilder gsonbuilder = (new GsonBuilder()).setPrettyPrinting();
gsonbuilder.registerTypeHierarchyAdapter(JsonListEntry.class, new JsonList.JsonListEntrySerializer(null));
this.b = gsonbuilder.create();
}
public boolean isEnabled() {
return this.e;
}
public void a(boolean flag) {
this.e = flag;
}
public File c() {
return this.c;
}
public void add(V v0) {
this.d.put(this.a(v0.getKey()), v0);
this.save();
}
public V get(K k0) {
// Torch start - reduce expire check
final long now = System.currentTimeMillis();
if ((now - lastExpireCheckTime) > EXPIRE_CHECK_INTERVAL) {
lastExpireCheckTime = now;
this.removeExpired();
}
// Torch end
return this.d.get(a(k0)); // CraftBukkit - fix decompile error
}
public void remove(K k0) {
this.d.remove(a(k0));
this.save();
}
public String[] getEntries() {
return this.d.keySet().toArray(new String[this.d.size()]);
}
// CraftBukkit start
public Collection<V> getValues() {
return this.d.values();
}
// CraftBukkit end
public boolean isEmpty() {
return this.d.size() < 1;
}
protected String a(K k) {
return Caches.objectString(k); // Torch - cache keys
}
public boolean contains(K k0) { return this.d(k0); } // OBFHELPER
protected boolean d(K k0) {
return this.d.containsKey(a(k0));
}
public void removeExpired() { this.h(); } // OBFHELPER
private void h() {
Iterator<V> iterator = this.d.values().iterator();
while (iterator.hasNext()) if (iterator.next().hasExpired()) iterator.remove(); // Torch - slight optimization
}
protected JsonListEntry<K> a(JsonObject jsonobject) {
return new JsonListEntry((Object) null, jsonobject);
}
public Map<String, V> getMap() { return this.e(); } // OBFHELPER
protected Map<String, V> e() {
return this.d;
}
@Async
public void save() {
Collection<V> values = this.d.values();
MCUtil.scheduleAsyncTask(() -> {
String jsonString = this.b.toJson(values);
BufferedWriter writer = null;
try {
writer = Files.newWriter(this.c, Charsets.UTF_8);
writer.write(jsonString);
} catch (IOException io) {
logger.warn("Failed to save {}", this.c.getName());
io.printStackTrace();
} finally {
IOUtils.closeQuietly(writer);
}
});
}
public void load() throws FileNotFoundException {
Collection collection = null;
BufferedReader bufferedreader = null;
try {
bufferedreader = Files.newReader(this.c, Charsets.UTF_8);
collection = (Collection) this.b.fromJson(bufferedreader, JsonList.f);
// Spigot Start
} catch ( java.io.FileNotFoundException ex )
{
org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.INFO, "Unable to find file {0}, creating it.", this.c );
} catch ( com.google.gson.JsonSyntaxException ex )
{
org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Unable to read file {0}, backing it up to {0}.backup and creating new copy.", this.c );
File backup = new File( this.c + ".backup" );
this.c.renameTo( backup );
this.c.delete();
// Spigot End
} finally {
IOUtils.closeQuietly(bufferedreader);
}
if (collection != null) {
this.d.clear();
Iterator iterator = collection.iterator();
while (iterator.hasNext()) {
JsonListEntry jsonlistentry = (JsonListEntry) iterator.next();
if (jsonlistentry.getKey() != null) {
this.d.put(this.a((K) jsonlistentry.getKey()), (V) jsonlistentry); // CraftBukkit - fix decompile error
}
}
}
}
class JsonListEntrySerializer implements JsonDeserializer<JsonListEntry<K>>, JsonSerializer<JsonListEntry<K>> {
private JsonListEntrySerializer() {}
public JsonElement a(JsonListEntry<K> jsonlistentry, Type type, JsonSerializationContext jsonserializationcontext) {
JsonObject jsonobject = new JsonObject();
jsonlistentry.a(jsonobject);
return jsonobject;
}
public JsonListEntry<K> a(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException {
if (jsonelement.isJsonObject()) {
JsonObject jsonobject = jsonelement.getAsJsonObject();
return JsonList.this.a(jsonobject);
} else {
return null;
}
}
@Override
public JsonElement serialize(JsonListEntry<K> object, Type type, JsonSerializationContext jsonserializationcontext) { // CraftBukkit - fix decompile error
return this.a(object, type, jsonserializationcontext);
}
@Override
public JsonListEntry<K> deserialize(JsonElement jsonelement, Type type, JsonDeserializationContext jsondeserializationcontext) throws JsonParseException { // CraftBukkit - fix decompile error
return this.a(jsonelement, type, jsondeserializationcontext);
}
JsonListEntrySerializer(Object object) {
this();
}
}
}