Last active
August 29, 2015 14:14
-
-
Save Techcable/2dce0a6f87bc2e2bba19 to your computer and use it in GitHub Desktop.
A UUIDFetcher for techcable's uuid service with caching
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.ref.SoftReference; | |
import java.io.BufferedReader; | |
import java.io.InputStreamReader; | |
import java.io.IOException; | |
import java.net.URL; | |
import java.util.HashMap; | |
import java.util.Map; | |
import java.util.UUID; | |
/** | |
* Utilities to lookup player names and uuids from techcable's uuid service | |
* This caches results so you won't have issues with the rate limit | |
* | |
* <p> | |
* <b>DONT Rely on Bukkit.getOfflinePlayer()</b> | |
* It doesn't cache and is a workaround solution | |
* | |
* evilmidgets fetchers are a fair solution, but they don't cache so you can run into ratelimits | |
* | |
* @author Techcable | |
*/ | |
public class UUIDFetcher { | |
private UUIDFetcher() {} | |
private static Cache<String, PlayerProfile> nameCache = new Cache<String, PlayerProfile>(); | |
private static Cache<UUID, PlayerProfile> idCache = new Cache<UUID, PlayerProfile>(); | |
/** | |
* Lookup a profile with the given name | |
* | |
* Returns null in the event of failure | |
* | |
* @param name look for a profile with this name | |
* @return a profile with the given name, or null if failed | |
*/ | |
public static PlayerProfile lookup(String name) { | |
if (name == null) return null; | |
if (nameCache.contains(name)) return nameCache.get(name); | |
String rawUuid = get("http://uuid.techcable.net/api/uuid/" + name); | |
if (name == null) return null; | |
if (rawUuid == "unknown" || rawUuid == "error") return null; | |
UUID id = UUID.fromString(rawUuid); | |
PlayerProfile player = new PlayerProfile(id, name); | |
nameCache.put(name, player); | |
return player; | |
} | |
/** | |
* Lookup a profile with the given uuid | |
* | |
* Returns null in the event of failure | |
* | |
* @param id look for a profile with this uuid | |
* @return a profile with the given id, or null if failed | |
*/ | |
public static PlayerProfile lookup(UUID id) { | |
if (id == null) return null; | |
if (idCache.contains(id)) return idCache.get(id); | |
String name = get("http://uuid.techcable.net/api/name/" + id.toString()); | |
if (name == null) return null; | |
if (name == "\"error\"") return null; | |
PlayerProfile player = new PlayerProfile(id, name); | |
idCache.put(id, player); | |
return player; | |
} | |
/** | |
* Represnents a player | |
* Contains their uuid and username | |
* | |
* @author Techcable | |
*/ | |
public static class PlayerProfile { | |
public PlayerProfile(UUID id, String name) { | |
this.id = id; | |
this.name = name; | |
} | |
private final UUID id; | |
private final String name; | |
/** | |
* Get this player's uuid | |
* | |
* @return this players uuid | |
*/ | |
public UUID getId() { | |
return id; | |
} | |
/** | |
* Get this player's name | |
* | |
* @return this player's name | |
*/ | |
public String getName() { | |
return name; | |
} | |
} | |
//Utilities | |
public static String get(String rawUrl) { | |
BufferedReader reader = null; | |
try { | |
URL url = new URL(rawUrl); | |
reader = new BufferedReader(new InputStreamReader(url.openStream())); | |
StringBuffer result = new StringBuffer(); | |
String line; | |
while ((line = reader.readLine()) != null) result.append(line); | |
return result.toString(); | |
} catch (IOException ex) { | |
ex.printStackTrace(); | |
return null; | |
} finally { | |
try { | |
if (reader != null) reader.close(); | |
} catch (IOException ex) { | |
ex.printStackTrace(); | |
return null; | |
} | |
} | |
} | |
private static class Cache<K, V> { | |
private long expireTime = 1000 * 60 * 5; //default 5 min | |
private Map<K, CachedEntry<V>> map = new HashMap<>(); | |
public boolean contains(K key) { | |
return map.containsKey(key) && get(key) != null; | |
} | |
public V get(K key) { | |
CachedEntry<V> entry = map.get(key); | |
if (entry == null) return null; | |
if (entry.isExpired()) { | |
map.remove(key); | |
return null; | |
} else { | |
return entry.getValue(); | |
} | |
} | |
public void put(K key, V value) { | |
map.put(key, new CachedEntry<V>(value, expireTime)); | |
} | |
private static class CachedEntry<V> { | |
public CachedEntry(V value, long expireTime) { | |
this.value = new SoftReference<V>(value); | |
this.expires = expireTime + System.currentTimeMillis(); | |
} | |
private final SoftReference<V> value; //Caching is low memory priortiy | |
private final long expires; | |
public V getValue() { | |
if (isExpired()) { | |
return null; | |
} | |
return value.get(); | |
} | |
public boolean isExpired() { | |
if (value.get() == null) return true; | |
return expires != -1 && expires > System.currentTimeMillis(); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment