Last active
August 29, 2015 14:14
-
-
Save DarkSeraphim/2f7e2e0ec82b22358af2 to your computer and use it in GitHub Desktop.
Heave ho! Reload persistent data without hacky JVM classloader stuff ;3
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 org.bukkit.Bukkit; | |
import org.bukkit.World; | |
import org.bukkit.plugin.java.JavaPlugin; | |
import org.bukkit.metadata.MetadataValue; | |
public class Persistence | |
{ | |
private static final String METADATA_KEY = "MyPersistentStorage"; | |
// ↓ This is the part that finds the name itself! | |
private static final String NAME_PATTERN = "main: ([a-z0-9.\\-_]*)"; | |
// And here it ends! (Do not modify beyond this) ↑ | |
private static final Class<? extends JavaPlugin> MAIN_CLASS; | |
private static volatile Persistence instance; | |
private final Map<String, Object> data; | |
private Persistence() | |
{ | |
// This should be safe enough in our reload scope | |
List<MetadataValue> data = Bukkit.getWorlds().get(0).getMetadata(METADATA_KEY); | |
JavaPlugin plugin = JavaPlugin.getPlugin(Persistence.MAIN_CLASS); | |
for(MetadataValue value : data) | |
{ | |
if(value.getOwningPlugin().equals(plugin)) | |
{ | |
if(value.value() instanceof Map) | |
{ | |
// Cast will always be safe - every Map will be assignable to a Map<Object, Object> | |
// As everything extends Object | |
Map<Object, Object> map = (Map<Object, Object>)value.value(); | |
// For typesafe keys | |
Iterator<Map.Entry<?, ?>> entryIterator = map.entrySet().iterator(); | |
while(entryIterator.hasNext()) | |
{ | |
Map.Entry<?, ?> entry = entryIterator.next(); | |
if(!(entry.getKey() instanceof String)) | |
{ | |
entryIterator.remove(); | |
} | |
} | |
this.data = Collections.synchronizedMap((Map<String, Object>)map); | |
return; | |
} | |
} | |
} | |
Map<String, Object> backend = new HashMap<String, Object>(); | |
Bukkit.getWorlds().get(0).setMetadata(METADATA_KEY, new FixedMetadataValue(plugin, backend)); | |
// If it hasn't been found in the metadata store, create a new one | |
this.data = Collections.synchronizedMap(backend); | |
} | |
private static Persistence getInstance() | |
{ | |
if(Persistence.instance == null) | |
{ | |
synchronized (Persistence.class) | |
{ | |
if (Persistence.instance == null) | |
{ | |
Persistence.instance = new Persistence(); | |
} | |
} | |
} | |
return Persistence.instance; | |
} | |
public static void set(String key, Object data) | |
{ | |
Persistence persistence = getInstance(); | |
persistence.data.put(key, data); | |
} | |
public static boolean has(String key) | |
{ | |
Persistence persistence = getInstance(); | |
return persistence.data.containsKey(key); | |
} | |
public static <T> T get(String key, T def) | |
{ | |
Persistence persistence = getInstance(); | |
Object obj = persistence.data.get(key); | |
return obj instanceof T ? obj : def; | |
} | |
public static boolean remove(String key) | |
{ | |
Persistence persistence = getInstance(); | |
return persistence.data.remove(key) != null; | |
} | |
static | |
{ | |
try | |
{ | |
URL url = getClassLoader().getResource("plugin.yml"); | |
if (url == null) | |
{ | |
throw IllegalStateException("No plugin.yml in your jar file, every plugin needs one!"); | |
} | |
URLConnection connection = url.openConnection(); | |
connection.setUseCaches(false); | |
StringBuilder data = new StringBuilder(); | |
byte[] buf = new byte[64]; | |
InputStream in = connection.getInputStream(); | |
int len; | |
while ((len = in.read(buf)) > 0) | |
{ | |
data.append(new String(buf, 0, len)); | |
} | |
// Pattern may vary, but this should catch most plugin names. | |
Matcher it = Pattern.compile(NAME_PATTERN, Pattern.CASE_INSENSITIVE).matcher(data); | |
if (it.matches()) | |
{ | |
MAIN_CLASS = Class.forName(it.group(1)); | |
} | |
else | |
{ | |
throw new IllegalStateException("Couldn't find the name of the plugin. Check your plugin.yml and the NAME_PATTERN value!"); | |
} | |
} | |
catch (IOException ex) | |
{ | |
throw new IllegalStateException("Failed to load plugin.yml from the jar file", ex); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment