mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-06-26 06:14:42 +02:00
More on GenericInstanceRegistry.
* Add a way to stay updated about the latest registration state for a class. * Add a class for the registry. * Let the registry log all registrations. * Make super interfaces for LogManager (simple logging of String/Throwable). Missing: * More streams (REGISTRY, PLAYER/CHECK_STATUS/EVENTS or just CHECKS at least). Make status rather the plugin status. Registry could have an extra file. * More efficient IGenericInstanceHandle use (wrap + reference counting).
This commit is contained in:
parent
0868e30994
commit
2bf3e14ab9
|
@ -14,7 +14,8 @@
|
|||
*/
|
||||
package fr.neatmonster.nocheatplus.logging;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import fr.neatmonster.nocheatplus.logging.details.ILogString;
|
||||
import fr.neatmonster.nocheatplus.logging.details.ILogThrowable;
|
||||
|
||||
/**
|
||||
* Central access point log manager with a bias towards String messages.
|
||||
|
@ -22,7 +23,7 @@ import java.util.logging.Level;
|
|||
* @author dev1mc
|
||||
*
|
||||
*/
|
||||
public interface LogManager {
|
||||
public interface LogManager extends ILogString, ILogThrowable {
|
||||
|
||||
/**
|
||||
* A stream that skips all messages. It's not registered officially.
|
||||
|
@ -99,24 +100,4 @@ public interface LogManager {
|
|||
*/
|
||||
public StreamID getStreamID(String name);
|
||||
|
||||
void debug(StreamID streamID, String message);
|
||||
|
||||
void info(StreamID streamID, String message);
|
||||
|
||||
void warning(StreamID streamID, String message);
|
||||
|
||||
void severe(StreamID streamID, String message);
|
||||
|
||||
void log(StreamID streamID, Level level, String message);
|
||||
|
||||
void debug(StreamID streamID, Throwable t);
|
||||
|
||||
void info(StreamID streamID, Throwable t);
|
||||
|
||||
void warning(StreamID streamID, Throwable t);
|
||||
|
||||
void severe(StreamID streamID, Throwable t);
|
||||
|
||||
void log(StreamID streamID, Level level, Throwable t);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package fr.neatmonster.nocheatplus.logging.details;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.StreamID;
|
||||
|
||||
/**
|
||||
* Allow to select/return a StgreamID instance.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
* @param <M>
|
||||
*/
|
||||
public interface IGetStreamId {
|
||||
|
||||
public StreamID getStreamId();
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package fr.neatmonster.nocheatplus.logging.details;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.StreamID;
|
||||
|
||||
/**
|
||||
* Standard logging for String messages.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface ILogString {
|
||||
|
||||
void debug(StreamID streamID, String message);
|
||||
|
||||
void info(StreamID streamID, String message);
|
||||
|
||||
void warning(StreamID streamID, String message);
|
||||
|
||||
void severe(StreamID streamID, String message);
|
||||
|
||||
void log(StreamID streamID, Level level, String message);
|
||||
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package fr.neatmonster.nocheatplus.logging.details;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.StreamID;
|
||||
|
||||
/**
|
||||
* Standard logging for Throwable throwables.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface ILogThrowable {
|
||||
|
||||
void debug(StreamID streamID, Throwable t);
|
||||
|
||||
void info(StreamID streamID, Throwable t);
|
||||
|
||||
void warning(StreamID streamID, Throwable t);
|
||||
|
||||
void severe(StreamID streamID, Throwable t);
|
||||
|
||||
void log(StreamID streamID, Level level, Throwable t);
|
||||
|
||||
}
|
|
@ -14,44 +14,63 @@
|
|||
*/
|
||||
package fr.neatmonster.nocheatplus.components.registry;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
|
||||
/**
|
||||
* A registry for unique instances of any class type.<br>
|
||||
* Currently there is no specification for what happens with registering for an
|
||||
* already registered class, neither if exceptions are thrown, nor if
|
||||
* dependencies will use those then.
|
||||
*
|
||||
* @author dev1mc
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface GenericInstanceRegistry {
|
||||
|
||||
/**
|
||||
* Register the instance by its own class.
|
||||
* @param instance
|
||||
*/
|
||||
public <T> T registerGenericInstance(T instance);
|
||||
|
||||
/**
|
||||
* Register an instance under for a super-class.
|
||||
* @todo The registry implementation might specify if overriding is allowed.
|
||||
* @param registerAs
|
||||
* @param instance
|
||||
* @return The previously registered instance. If none was registered, null is returned.
|
||||
*/
|
||||
public <T, TI extends T> T registerGenericInstance(Class<T> registerFor, TI instance);
|
||||
|
||||
/**
|
||||
* Retrieve the instance registered for the given class.
|
||||
* @param registeredBy
|
||||
* @return The instance, or null, if none is registered.
|
||||
*/
|
||||
public <T> T getGenericInstance(Class<T> registeredFor);
|
||||
|
||||
/**
|
||||
* Remove a registration. The registry implementation might specify id removing is allowed.
|
||||
* @param registeredFor
|
||||
* @return The previously registered instance. If none was registered, null is returned.
|
||||
*/
|
||||
public <T> T unregisterGenericInstance(Class<T> registeredFor);
|
||||
|
||||
|
||||
/**
|
||||
* Register the instance by its own class. This demands type parameters to
|
||||
* be aligned to the actual class.
|
||||
*
|
||||
* @param instance
|
||||
*/
|
||||
public <T> T registerGenericInstance(T instance);
|
||||
|
||||
/**
|
||||
* Register an instance under for a super-class.
|
||||
*
|
||||
* @todo The registry implementation might specify if overriding is allowed.
|
||||
* @param registerAs
|
||||
* @param instance
|
||||
* @return The previously registered instance. If none was registered, null
|
||||
* is returned.
|
||||
*/
|
||||
public <T, TI extends T> T registerGenericInstance(Class<T> registerFor, TI instance);
|
||||
|
||||
/**
|
||||
* Retrieve the instance registered for the given class.
|
||||
*
|
||||
* @param registeredBy
|
||||
* @return The instance, or null, if none is registered.
|
||||
*/
|
||||
public <T> T getGenericInstance(Class<T> registeredFor);
|
||||
|
||||
/**
|
||||
* Remove a registration. The registry implementation might specify id
|
||||
* removing is allowed.
|
||||
*
|
||||
* @param registeredFor
|
||||
* @return The previously registered instance. If none was registered, null
|
||||
* is returned.
|
||||
*/
|
||||
public <T> T unregisterGenericInstance(Class<T> registeredFor);
|
||||
|
||||
/**
|
||||
* Get a self-updating handle for conveniently getting the currently
|
||||
* registered instance.
|
||||
*
|
||||
* @param registeredFor
|
||||
* @return
|
||||
*/
|
||||
public <T> IGenericInstanceHandle<T> getGenericInstanceHandle(Class<T> registeredFor);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package fr.neatmonster.nocheatplus.components.registry.event;
|
||||
|
||||
/**
|
||||
* Convenience to retrieve the currently registered instance. Note that
|
||||
* registrations by other plugins might be problematic, thus removing
|
||||
* registrations and stored IGenericInstanceHandle instances is within the
|
||||
* responsibility of the hooking plugin.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
* @param <T>
|
||||
* The type instances are registered for.
|
||||
*/
|
||||
public interface IGenericInstanceHandle<T> {
|
||||
|
||||
// TODO: <? extends T> ?
|
||||
|
||||
/**
|
||||
* Get the currently registered instance.
|
||||
*
|
||||
* @return
|
||||
* @throws RuntimeException,
|
||||
* if disableHandle has been called.
|
||||
*/
|
||||
public T getHandle();
|
||||
|
||||
/**
|
||||
* Unlink from the registry. Subsequent calls to getHandle will yield a
|
||||
* RuntimeException, while disableHandle can still be called without effect.
|
||||
* This may not be necessary, if the registration lasts during an entire
|
||||
* runtime, however if an object that holds IGenericInstanceHandle instances
|
||||
* gets overridden on reloading the configuration of the plugin, keeping
|
||||
* handles may leak a little bit of memory and increase CPU load with each
|
||||
* time such happens. Often changing registration is not a typical use-case.
|
||||
* This can not be undone.
|
||||
*/
|
||||
public void disableHandle();
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package fr.neatmonster.nocheatplus.components.registry.event;
|
||||
|
||||
/**
|
||||
* Receive Notifications about generic instance registry events. Listeners may
|
||||
* be possible to register even before an actual instance has been registered
|
||||
* (and even before it's known to the registry that anything is intended to be
|
||||
* registered) - subject to change.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IGenericInstanceRegistryListener<T> {
|
||||
|
||||
// TODO: <? extends T> ?
|
||||
|
||||
/**
|
||||
* Registration, without an entry being present.
|
||||
*
|
||||
* @param registerFor
|
||||
* @param instance
|
||||
* Might be null, if the registry allows that.
|
||||
*/
|
||||
public void onGenericInstanceRegister(Class<T> registerFor, T instance);
|
||||
|
||||
/**
|
||||
* An already registered entry gets overridden.
|
||||
*
|
||||
* @param registerFor
|
||||
* @param newInstance
|
||||
* The instance that just got registered. Might be null, if the
|
||||
* registry allows that.
|
||||
* @param oldInstance
|
||||
* The instance that had been registered before. Might be null,
|
||||
* if the registry allows that.
|
||||
*/
|
||||
public void onGenericInstanceOverride(Class<T> registerFor, T newInstance, T oldInstance);
|
||||
|
||||
/**
|
||||
* A registration is removed explicitly.
|
||||
*
|
||||
* @param registerFor
|
||||
* @param oldInstance
|
||||
* The instance that had been registered before. Might be null,
|
||||
* if the registry allows that.
|
||||
*/
|
||||
public void onGenericInstanceRemove(Class<T> registerFor, T oldInstance);
|
||||
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package fr.neatmonster.nocheatplus.components.registry.event;
|
||||
|
||||
/**
|
||||
* Rather an internal interface.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public interface IUnregisterGenericInstanceListener {
|
||||
|
||||
public <T> void unregisterGenericInstanceListener(Class<T> registeredFor, IGenericInstanceHandle<T> listener);
|
||||
|
||||
}
|
|
@ -82,6 +82,8 @@ import fr.neatmonster.nocheatplus.compat.versions.GenericVersion;
|
|||
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
|
||||
import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
|
||||
import fr.neatmonster.nocheatplus.components.registry.ComponentRegistry;
|
||||
import fr.neatmonster.nocheatplus.components.registry.DefaultGenericInstanceRegistry;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
import fr.neatmonster.nocheatplus.components.registry.feature.ComponentWithName;
|
||||
import fr.neatmonster.nocheatplus.components.registry.feature.ConsistencyChecker;
|
||||
import fr.neatmonster.nocheatplus.components.registry.feature.DisableListener;
|
||||
|
@ -110,7 +112,9 @@ import fr.neatmonster.nocheatplus.hooks.allviolations.AllViolationsHook;
|
|||
import fr.neatmonster.nocheatplus.logging.BukkitLogManager;
|
||||
import fr.neatmonster.nocheatplus.logging.LogManager;
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
import fr.neatmonster.nocheatplus.logging.StreamID;
|
||||
import fr.neatmonster.nocheatplus.logging.Streams;
|
||||
import fr.neatmonster.nocheatplus.logging.details.IGetStreamId;
|
||||
import fr.neatmonster.nocheatplus.permissions.PermissionUtil;
|
||||
import fr.neatmonster.nocheatplus.permissions.PermissionUtil.CommandProtectionEntry;
|
||||
import fr.neatmonster.nocheatplus.permissions.Permissions;
|
||||
|
@ -184,9 +188,6 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
/** The event listeners. */
|
||||
private final List<Listener> listeners = new ArrayList<Listener>();
|
||||
|
||||
/** Storage for generic instances registration. */
|
||||
private final Map<Class<?>, Object> genericInstances = new HashMap<Class<?>, Object>();
|
||||
|
||||
/** Components that need notification on reloading.
|
||||
* (Kept here, for if during runtime some might get added.)*/
|
||||
private final List<INotifyReload> notifyReload = new LinkedList<INotifyReload>();
|
||||
|
@ -230,6 +231,9 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
/** Listener for the BlockChangeTracker (register once, lazy). */
|
||||
private BlockChangeListener blockChangeListener = null;
|
||||
|
||||
private final DefaultGenericInstanceRegistry genericInstanceRegistry = new DefaultGenericInstanceRegistry();
|
||||
|
||||
|
||||
/** Tick listener that is only needed sometimes (component registration). */
|
||||
protected final OnDemandTickListener onDemandTickListener = new OnDemandTickListener() {
|
||||
@Override
|
||||
|
@ -262,6 +266,12 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
private boolean clearExemptionsOnJoin = true;
|
||||
private boolean clearExemptionsOnLeave = true;
|
||||
|
||||
private StreamID getRegistryStreamId() {
|
||||
// TODO: Select by config, or add Streams.REGISTRY for a new default.
|
||||
// For now prefer log file, unless extended status is set.
|
||||
return ConfigManager.getConfigFile().getBoolean(ConfPaths.LOGGING_EXTENDED_STATUS) ? Streams.STATUS : Streams.DEFAULT_FILE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove expired entries.
|
||||
*/
|
||||
|
@ -737,7 +747,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
// Just in case: clear the subComponentHolders.
|
||||
subComponentholders.clear();
|
||||
// Generic instances registry.
|
||||
genericInstances.clear();
|
||||
genericInstanceRegistry.clear();
|
||||
// Feature tags.
|
||||
featureTags.clear();
|
||||
// BlockChangeTracker.
|
||||
|
@ -850,6 +860,14 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
StaticLog.setUseLogManager(true);
|
||||
logManager.info(Streams.INIT, "Logging system initialized.");
|
||||
logManager.info(Streams.INIT, "Detected Minecraft version: " + ServerVersion.getMinecraftVersion());
|
||||
genericInstanceRegistry.setLogger(
|
||||
logManager, new IGetStreamId() {
|
||||
@Override
|
||||
public StreamID getStreamId() {
|
||||
// TODO Auto-generated method stub
|
||||
return NoCheatPlus.this.getRegistryStreamId();
|
||||
}
|
||||
}, "[GenericInstanceRegistry] ");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1468,33 +1486,29 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getGenericInstance(Class<T> registeredFor) {
|
||||
return genericInstanceRegistry.getGenericInstance(registeredFor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T registerGenericInstance(T instance) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Class<T> clazz = (Class<T>) instance.getClass();
|
||||
T registered = getGenericInstance(clazz);
|
||||
genericInstances.put(clazz, instance);
|
||||
return registered;
|
||||
return genericInstanceRegistry.registerGenericInstance(instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, TI extends T> T registerGenericInstance(Class<T> registerFor, TI instance) {
|
||||
T registered = getGenericInstance(registerFor);
|
||||
genericInstances.put(registerFor, instance);
|
||||
return registered;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getGenericInstance(Class<T> registeredFor) {
|
||||
return (T) genericInstances.get(registeredFor);
|
||||
return genericInstanceRegistry.registerGenericInstance(registerFor, instance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T unregisterGenericInstance(Class<T> registeredFor) {
|
||||
T registered = getGenericInstance(registeredFor); // Convenience.
|
||||
genericInstances.remove(registeredFor);
|
||||
return registered;
|
||||
return genericInstanceRegistry.unregisterGenericInstance(registeredFor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> IGenericInstanceHandle<T> getGenericInstanceHandle(Class<T> registeredFor) {
|
||||
return genericInstanceRegistry.getGenericInstanceHandle(registeredFor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -141,7 +141,6 @@ public class RegistryHelper {
|
|||
public static <T, ET extends T> T registerGenericInstance(Class<T> registerFor, ET result) {
|
||||
if (result != null) {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().registerGenericInstance(registerFor, result);
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "Registered for " + registerFor.getName() + ": " + result.getClass().getName());
|
||||
}
|
||||
else {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().info(Streams.STATUS, "Could not register an instance for: " + registerFor.getName());
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
package fr.neatmonster.nocheatplus.components.registry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.GenericInstanceHandle;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceRegistryListener;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IUnregisterGenericInstanceListener;
|
||||
import fr.neatmonster.nocheatplus.logging.details.IGetStreamId;
|
||||
import fr.neatmonster.nocheatplus.logging.details.ILogString;
|
||||
|
||||
public class DefaultGenericInstanceRegistry implements GenericInstanceRegistry, IUnregisterGenericInstanceListener {
|
||||
|
||||
/** Storage for generic instances registration. */
|
||||
private final Map<Class<?>, Object> instances = new HashMap<Class<?>, Object>();
|
||||
|
||||
/** Listeners for registry events. */
|
||||
private final Map<Class<?>, Collection<IGenericInstanceRegistryListener<?>>> listeners = new HashMap<Class<?>, Collection<IGenericInstanceRegistryListener<?>>>();
|
||||
|
||||
/** Handles created within this class, that have to be detached. */
|
||||
private final Set<IGenericInstanceHandle<?>> ownedHandles = new LinkedHashSet<IGenericInstanceHandle<?>>();
|
||||
|
||||
private ILogString logger = null;
|
||||
|
||||
private IGetStreamId selectStream;
|
||||
|
||||
private String logPrefix;
|
||||
|
||||
public void setLogger(ILogString logger, IGetStreamId selectStream, String logPrefix) {
|
||||
this.logger = logger;
|
||||
this.selectStream = selectStream;
|
||||
this.logPrefix = logPrefix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void unregisterGenericInstanceListener(Class<T> registeredFor, IGenericInstanceHandle<T> listener) {
|
||||
Collection<IGenericInstanceRegistryListener<?>> registered = listeners.get(registeredFor);
|
||||
if (registered != null) {
|
||||
registered.remove(listener);
|
||||
if (registered.isEmpty()) {
|
||||
listeners.remove(registeredFor);
|
||||
}
|
||||
}
|
||||
if ((listener instanceof IGenericInstanceHandle<?>) && ownedHandles.contains(listener)) {
|
||||
ownedHandles.remove(listener);
|
||||
((IGenericInstanceHandle<?>) listener).disableHandle();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T registerGenericInstance(T instance) {
|
||||
return registerGenericInstance((Class<T>) instance.getClass(), instance);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T, TI extends T> T registerGenericInstance(Class<T> registerFor, TI instance) {
|
||||
T registered = getGenericInstance(registerFor);
|
||||
final boolean had = instances.containsKey(registerFor);
|
||||
instances.put(registerFor, instance);
|
||||
Collection<IGenericInstanceRegistryListener<?>> registeredListeners = listeners.get(registerFor);
|
||||
if (registeredListeners != null) {
|
||||
for (IGenericInstanceRegistryListener<?> rawListener : registeredListeners) {
|
||||
if (had) {
|
||||
((IGenericInstanceRegistryListener<T>) rawListener).onGenericInstanceOverride(registerFor, instance, registered);
|
||||
}
|
||||
else {
|
||||
((IGenericInstanceRegistryListener<T>) rawListener).onGenericInstanceRegister(registerFor, instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (had) {
|
||||
logRegistryEvent("Registered (override) for " + registerFor.getName() + ": " + instance.getClass().getName());
|
||||
}
|
||||
else {
|
||||
logRegistryEvent("Registered for " + registerFor.getName() + ": " + instance.getClass().getName());
|
||||
}
|
||||
return registered;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getGenericInstance(Class<T> registeredFor) {
|
||||
return (T) instances.get(registeredFor);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T unregisterGenericInstance(Class<T> registeredFor) {
|
||||
T registered = getGenericInstance(registeredFor); // Convenience.
|
||||
final boolean had = instances.containsKey(registeredFor);
|
||||
instances.remove(registeredFor);
|
||||
Collection<IGenericInstanceRegistryListener<?>> registeredListeners = listeners.get(registeredFor);
|
||||
if (registeredListeners != null) {
|
||||
for (IGenericInstanceRegistryListener<?> rawListener : registeredListeners) {
|
||||
((IGenericInstanceRegistryListener<T>) rawListener).onGenericInstanceRemove(registeredFor, registered);
|
||||
}
|
||||
}
|
||||
if (had) {
|
||||
logRegistryEvent("Unregister, remove mapping for: " + registeredFor.getName());
|
||||
}
|
||||
else {
|
||||
logRegistryEvent("Unregister, no mapping present for: " + registeredFor.getName());
|
||||
}
|
||||
return registered;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> IGenericInstanceHandle<T> getGenericInstanceHandle(Class<T> registeredFor) {
|
||||
/*
|
||||
* More efficient should be to return a wrapper for a unique instance,
|
||||
* for which disableHandle runs once, so only one listener per
|
||||
* registered class is necessary, which then uses reference counting for
|
||||
* actual removal. That's double-wrapped then (returned instance disable
|
||||
* once -> reference counting instance -> actual instance).
|
||||
*/
|
||||
final IGenericInstanceHandle<T> handle = new GenericInstanceHandle<T>(registeredFor, this, this);
|
||||
ownedHandles.add(handle);
|
||||
Collection<IGenericInstanceRegistryListener<?>> registered = listeners.get(registeredFor);
|
||||
if (registered == null) {
|
||||
registered = new HashSet<IGenericInstanceRegistryListener<?>>();
|
||||
listeners.put(registeredFor, registered);
|
||||
}
|
||||
registered.add((IGenericInstanceRegistryListener<?>) handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
instances.clear();
|
||||
listeners.clear();
|
||||
// TODO: consider fire unregister or add a removal method ?
|
||||
// Force detach all handles.
|
||||
for (IGenericInstanceHandle<?> handle : new ArrayList<IGenericInstanceHandle<?>>(ownedHandles)) {
|
||||
handle.disableHandle();
|
||||
}
|
||||
ownedHandles.clear();
|
||||
logRegistryEvent("Registry cleared.");
|
||||
}
|
||||
|
||||
protected void logRegistryEvent(String message) {
|
||||
if (logger != null) {
|
||||
logger.info(selectStream.getStreamId(), logPrefix == null ? message : logPrefix + message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
package fr.neatmonster.nocheatplus.components.registry.event;
|
||||
|
||||
import fr.neatmonster.nocheatplus.components.registry.GenericInstanceRegistry;
|
||||
|
||||
/**
|
||||
* Default implementation for retrieving a IGenericInstanceHandle from a
|
||||
* registry.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public class GenericInstanceHandle<T> implements IGenericInstanceRegistryListener<T>, IGenericInstanceHandle<T> {
|
||||
|
||||
// TODO: <? extends T> ?
|
||||
// TODO: Might move to NCPPlugin, or later split (mostly) interface based api from default implementations.
|
||||
|
||||
private GenericInstanceRegistry registry;
|
||||
private IUnregisterGenericInstanceListener unregister;
|
||||
private Class<T> registeredFor;
|
||||
private T handle = null;
|
||||
private boolean initialized = false;
|
||||
private boolean disabled = false;
|
||||
|
||||
// TODO: Remove method?
|
||||
|
||||
/**
|
||||
* Note that this doesn't register with the registry, as the registry may
|
||||
* return unique handles on request rather.
|
||||
*
|
||||
* @param registeredFor
|
||||
* @param registry
|
||||
* @param unregister
|
||||
*/
|
||||
public GenericInstanceHandle(Class<T> registeredFor, GenericInstanceRegistry registry, IUnregisterGenericInstanceListener unregister) {
|
||||
this.registry = registry;
|
||||
this.unregister = unregister;
|
||||
this.registeredFor = registeredFor;
|
||||
}
|
||||
|
||||
private T fetchHandle() {
|
||||
return registry.getGenericInstance(registeredFor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericInstanceRegister(Class<T> registerFor, T instance) {
|
||||
this.handle = instance;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericInstanceOverride(Class<T> registerFor, T newInstance, T oldInstance) {
|
||||
this.handle = newInstance;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGenericInstanceRemove(Class<T> registerFor, T oldInstance) {
|
||||
this.handle = null;
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getHandle() {
|
||||
if (initialized) {
|
||||
return handle;
|
||||
}
|
||||
else if (disabled) {
|
||||
throw new RuntimeException("Already disabled.");
|
||||
}
|
||||
else {
|
||||
return fetchHandle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableHandle() {
|
||||
if (unregister != null) {
|
||||
disabled = true;
|
||||
initialized = false;
|
||||
handle = null;
|
||||
registeredFor = null;
|
||||
registry = null;
|
||||
unregister.unregisterGenericInstanceListener(registeredFor, this);
|
||||
unregister = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ import fr.neatmonster.nocheatplus.compat.blocks.BlockChangeTracker;
|
|||
import fr.neatmonster.nocheatplus.compat.bukkit.MCAccessBukkit;
|
||||
import fr.neatmonster.nocheatplus.components.NoCheatPlusAPI;
|
||||
import fr.neatmonster.nocheatplus.components.registry.ComponentRegistry;
|
||||
import fr.neatmonster.nocheatplus.components.registry.event.IGenericInstanceHandle;
|
||||
import fr.neatmonster.nocheatplus.logging.LogManager;
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
|
||||
|
@ -82,6 +83,11 @@ public class PluginTests {
|
|||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> IGenericInstanceHandle<T> getGenericInstanceHandle(Class<T> registeredFor) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addComponent(Object obj, boolean allowComponentFactory) {
|
||||
throw new UnsupportedOperationException();
|
||||
|
|
Loading…
Reference in New Issue
Block a user