From 1acd7401c7183f2391761d087e4623bfbaf4a16e Mon Sep 17 00:00:00 2001 From: Wesley Wolfe Date: Tue, 7 Aug 2012 00:16:57 -0500 Subject: Add Warning API and settings for Deprecated events --- src/main/java/org/bukkit/Bukkit.java | 5 ++ src/main/java/org/bukkit/Server.java | 8 ++ src/main/java/org/bukkit/Warning.java | 93 ++++++++++++++++++++++ .../bukkit/event/player/AsyncPlayerChatEvent.java | 5 +- .../org/bukkit/event/player/PlayerChatEvent.java | 9 ++- .../org/bukkit/plugin/java/JavaPluginLoader.java | 12 ++- 6 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/bukkit/Warning.java (limited to 'src') diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index e9c408c5..1d0fa1c3 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -8,6 +8,7 @@ import java.util.Set; import java.util.UUID; import java.util.logging.Logger; +import org.bukkit.Warning.WarningState; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; import org.bukkit.command.PluginCommand; @@ -373,4 +374,8 @@ public final class Bukkit { public static String getMotd() { return server.getMotd(); } + + public static WarningState getWarningState() { + return server.getWarningState(); + } } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java index 32272443..361ad17d 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -8,6 +8,7 @@ import java.util.Set; import java.util.UUID; import java.util.logging.Logger; +import org.bukkit.Warning.WarningState; import org.bukkit.command.CommandException; import org.bukkit.command.CommandSender; import org.bukkit.command.ConsoleCommandSender; @@ -651,4 +652,11 @@ public interface Server extends PluginMessageRecipient { * @returns the servers MOTD */ String getMotd(); + + /** + * Gets the current warning state for the server + * + * @return The configured WarningState + */ + public WarningState getWarningState(); } \ No newline at end of file diff --git a/src/main/java/org/bukkit/Warning.java b/src/main/java/org/bukkit/Warning.java new file mode 100644 index 00000000..8ac3270e --- /dev/null +++ b/src/main/java/org/bukkit/Warning.java @@ -0,0 +1,93 @@ +package org.bukkit; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.Map; + +import com.google.common.collect.ImmutableMap; + +/** + * This designates the warning state for a specific item. + * When the server settings dictate 'default' warnings, warnings are printed if the {@link #value()} is true. + */ +@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface Warning { + /** + * This represents the states that server verbose for warnings may be. + */ + public enum WarningState { + /** + * Indicates all warnings should be printed for deprecated items. + */ + ON, + /** + * Indicates no warnings should be printed for deprecated items. + */ + OFF, + /** + * Indicates each warning would default to the configured {@link Warning} annotation, or always if annotation not found. + */ + DEFAULT; + + private static final Map values = ImmutableMap.builder() + .put("off", OFF) + .put("false", OFF) + .put("f", OFF) + .put("no", OFF) + .put("n", OFF) + .put("on", ON) + .put("true", ON) + .put("t", ON) + .put("yes", ON) + .put("y", ON) + .put("", DEFAULT) + .put("d", DEFAULT) + .put("default", DEFAULT) + .build(); + + /** + * This method checks the provided warning should be printed for this state + * @param warning The warning annotation added to a deprecated item + * @return ON is always True
+ * OFF is always false
+ * DEFAULT is false if and only if annotation is not null and specifies false for {@link Warning#value()}, true otherwise. + */ + public boolean printFor(Warning warning) { + if (this == DEFAULT) { + return warning == null || warning.value(); + } + return this == ON; + } + + /** + * This method returns the corresponding warning state for the given string value. + * @param value The string value to check + * @return {@link #DEFAULT} if not found, or the respective WarningState + */ + public static WarningState value(final String value) { + if (value == null) { + return DEFAULT; + } + WarningState state = values.get(value.toLowerCase()); + if (state == null) { + return DEFAULT; + } + return state; + } + } + + /** + * This sets if the deprecation warnings when registering events gets printed when the setting is in the default state. + * @return false normally, or true to encourage warning printout + */ + boolean value() default false; + + /** + * This can provide detailed information on why the event is deprecated. + * @return The reason an event is deprecated + */ + String reason() default ""; +} diff --git a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java index e5011391..916783f7 100644 --- a/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java +++ b/src/main/java/org/bukkit/event/player/AsyncPlayerChatEvent.java @@ -10,7 +10,10 @@ import org.bukkit.event.HandlerList; /** * This event will sometimes fire synchronously, depending on how it was triggered. * The constructor provides a boolean to indicate if the event was fired synchronously or asynchronously. - * If a plugin causes a Player to chat with {@link Player#chat(String)} or by other general means, this event will be synchronous.
+ * When asynchronous, this event can be called from any thread, but the main thread, and has limited access to the API.
+ *
+ * If a player is the direct cause of this event by incoming packet, this event will be asynchronous. + * If a plugin triggers this event by compelling a player to chat, this event will be synchronous.
*
* Care should be taken to check {@link #isAsynchronous()} and treat the event appropriately. */ diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java index 481dbaaa..4872030d 100644 --- a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java @@ -5,17 +5,20 @@ import java.util.HashSet; import java.util.Set; import org.apache.commons.lang.Validate; +import org.bukkit.Warning; import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; /** * Holds information for player chat and commands - * @deprecated This event was broken in 1.3, where chat should be asynchronous. - * It is deprecated because listening for it is detrimental to server performance. - * {@link AsyncPlayerChatEvent} is the encouraged alternative. + * @deprecated This event will fire from the main thread and allows the use of all of the Bukkit API, unlike the {@link AsyncPlayerChatEvent}.
+ *
+ * Listening to this event forces chat to wait for the main thread which causes delays for chat.
+ * {@link AsyncPlayerChatEvent} is the encouraged alternative for thread safe implementations. */ @Deprecated +@Warning(reason="Listening to this event forces chat to wait for the main thread, delaying chat messages.") public class PlayerChatEvent extends PlayerEvent implements Cancellable { private static final HandlerList handlers = new HandlerList(); private boolean cancel = false; diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index bebfcc28..cf54ba84 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -23,6 +23,8 @@ import java.util.regex.Pattern; import org.apache.commons.lang.Validate; import org.bukkit.Bukkit; import org.bukkit.Server; +import org.bukkit.Warning; +import org.bukkit.Warning.WarningState; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.configuration.serialization.ConfigurationSerialization; import org.bukkit.event.Event; @@ -299,16 +301,22 @@ public class JavaPluginLoader implements PluginLoader { for (Class clazz = eventClass; Event.class.isAssignableFrom(clazz); clazz = clazz.getSuperclass()) { // This loop checks for extending deprecated events if (clazz.getAnnotation(Deprecated.class) != null) { + Warning warning = clazz.getAnnotation(Warning.class); + WarningState warningState = server.getWarningState(); + if (!warningState.printFor(warning)) { + break; + } plugin.getLogger().log( Level.WARNING, String.format( "\"%s\" has registered a listener for %s on method \"%s\", but the event is Deprecated." + - " Server performance will be affected; please notify the authors %s.", + " \"%s\"; please notify the authors %s.", plugin.getDescription().getFullName(), clazz.getName(), method.toGenericString(), + (warning != null && warning.reason().length() != 0) ? warning.reason() : "Server performance will be affected", Arrays.toString(plugin.getDescription().getAuthors().toArray())), - new AuthorNagException(null)); + warningState == WarningState.ON ? new AuthorNagException(null) : null); break; } } -- cgit v1.2.3