package net.obnoxint.mcdev.util;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPluginLoader;
/**
* <p>
* This class can help to achieve a reference to any plugin instance loaded by a {@link JavaPluginLoader} if the implementing {@link Plugin} is also loaded by the same
* JavaPluginLoader.
* </p>
* <p>
* If used inside an instance of Thread, this class will try to acquire a reference to a Plugin-instance of the name declared in the constructor call. The run() method can also be
* called manually but will block until the reference was acquired. It is therefore recommended to call the run() method by the start() method of a Thread-instance.
* </p>
* <p>
* As soon as the reference was acquired the getPlugin() method will return the Plugin-instance. Before that it will always return null.
* </p>
*/
public final class PluginInstanceRequirementHelper implements Runnable {
/**
* <p>
* A class implementing this interface must be passed to the constructor of {@link PluginInstanceRequirementHelper}. As soon as a reference to the requested plugin was
* acquired, the onPluginInstanceAcquired()-method will be called passing a reference to the requested {@link Plugin}
* </p>
* <p>
* The same instance of the implementing class can be (re-)used to acquire different plugin references.
* </p>
*/
public static interface PluginInstanceRequester {
/**
* Will be called by a {@link PluginInstanceRequirementHelper} as soon as a reference to the requested {@link Plugin} was acquired. The passed reference
* is synchronized and this method should therefore return as soon as possible.
*
* @param plugin
*/
public void onPluginInstanceAcquired(Plugin plugin);
}
private static final long INTERVAL = 100L;
private boolean acquired = false;
private boolean stopped = false;
private Plugin plugin = null;
private final String pluginName;
private final PluginInstanceRequester requester;
/**
* Creates a new PluginInstanceRequirementHelper.
*
* @param pluginName the name of the requested plugin. Must not be null and pluginName.trim().isEmpty must return false or an IllegalArgumentException will
* be thrown.
* @param requester the instance of {@link PluginInstanceRequester} to notify as soon as a reference was acquired.
*/
public PluginInstanceRequirementHelper(final String pluginName, final PluginInstanceRequester requester) {
if (pluginName == null || requester == null || pluginName.trim().isEmpty()) {
throw new IllegalArgumentException();
}
this.pluginName = pluginName.trim();
this.requester = requester;
}
/**
* Gets the acquired {@link Plugin} reference.
*
* @return the {@link Plugin} or null if not acquired.
*/
public Plugin getPlugin() {
return plugin;
}
/**
* @return true if a reference to the requested plugin was acquired.
*/
public boolean isAcquired() {
return acquired;
}
/**
* @return true if the execution has been stopped by calling the stop() method.
*/
public boolean isStopped() {
return stopped;
}
/**
* Manually resumes the PluginInstanceRequirementHelper. Counterpart to stop(). Has no effect if a reference to the requested plugin is already acquired.
*/
public void resume() {
stopped = false;
}
@Override
public void run() {
long lastRun = System.currentTimeMillis();
synchronized (this) {
while (!isAcquired() && !isStopped() && (lastRun + INTERVAL < System.currentTimeMillis())) {
setPlugin(Bukkit.getPluginManager().getPlugin(getPluginName()));
lastRun += INTERVAL;
}
}
}
/**
* Manually stops the PluginInstanceRequirementHelper from trying to acquire a reference to the requested plugin.
*/
public void stop() {
stopped = true;
}
private String getPluginName() {
return pluginName;
}
private PluginInstanceRequester getRequester() {
return requester;
}
private void setAcquired() {
acquired = true;
stop();
synchronized (plugin) {
getRequester().onPluginInstanceAcquired(getPlugin());
}
}
private void setPlugin(final Plugin plugin) {
if (plugin != null) {
this.plugin = plugin;
setAcquired();
}
}
}