diff --git a/buildSrc/README.md b/buildSrc/README.md new file mode 100644 index 00000000..4c1837ff --- /dev/null +++ b/buildSrc/README.md @@ -0,0 +1,7 @@ +# HeadlessMc-Modules + +A gradle plugin allowing us to generate Java 9+ module-info classes. For an example take a look at the +headlessmc-lwjgl [build.gradle](../headlessmc-lwjgl/build.gradle), there we open all packages in order to allow the +transformed lwjgl classes to access the RedirectionApi (to do that we also need to transform lwjgls' module-info to open +the headlessmc.lwjgl module). I tried around with other gradle plugins which allow you to cross compile to Java 8 while +generating module-info classes but all caused problems in one way or the other. diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMc.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMc.java index 7691628a..5c760bcb 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMc.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMc.java @@ -4,17 +4,52 @@ import me.earth.headlessmc.api.command.line.CommandLine; import me.earth.headlessmc.api.config.HasConfig; import me.earth.headlessmc.api.exit.ExitManager; +import me.earth.headlessmc.logging.Logger; import me.earth.headlessmc.logging.LoggingService; +/** + * Represents a HeadlessMc instance. + * An instance handles commands, logging and configuration and exiting the process. + */ public interface HeadlessMc extends LogsMessages, HasConfig { + /** + * Safe Wrapper for dev.xdark.deencapsulation.Deencapsulation, + * which can be used to access classes beyond Java 9 module boundaries. + * + * @return a service that can be used to access classes beyond Java 9 module boundaries. + */ Deencapsulator getDeencapsulator(); + /** + * Returns the command line belonging to this instance. + * The command line manages commands and the terminal for this HeadlessMc instance. + * + * @return the command line instance managing commands and the terminal for this HeadlessMc instance. + */ CommandLine getCommandLine(); + /** + * Instead of calling {@link System#exit(int)} it is advised to call this instead. + * + * @return the manager managing exiting this java process. + */ ExitManager getExitManager(); + /** + * The LoggingService for this instance. + * Configures {@link Logger}s. + * + * @return the logging service for this instance. + */ LoggingService getLoggingService(); + /** + * Logs the given message in a human-readable format instead of logging it. + * This method is meant to be used instead of a logger for communicating + * console output to the user. + * + * @param message the message to log on the console. + */ @Override default void log(String message) { getCommandLine().getInAndOutProvider().getOut().get().println(message); diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMcImpl.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMcImpl.java index 17445bbf..e5ab2c74 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMcImpl.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/HeadlessMcImpl.java @@ -10,6 +10,9 @@ import me.earth.headlessmc.api.exit.ExitManager; import me.earth.headlessmc.logging.LoggingService; +/** + * A default implementation for the {@link HeadlessMc} interface. + */ @Getter @RequiredArgsConstructor public class HeadlessMcImpl implements HeadlessMc { diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommand.java index ed3a24f1..4aac7272 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommand.java @@ -3,6 +3,7 @@ import lombok.Data; import me.earth.headlessmc.api.command.Command; import me.earth.headlessmc.api.command.CommandException; +import me.earth.headlessmc.api.command.line.CommandLine; import me.earth.headlessmc.api.util.ReflectionUtil; import org.jetbrains.annotations.Nullable; @@ -12,10 +13,20 @@ import java.util.Map; /** + * A {@link Command} implementation that delegates to another command. + * This delegation happens via reflection so any object that exposes the same methods as {@link Command} can be used. + * This is generally meant for environments where the Command class has been loaded multiple times from multiple ClassLoaders. + * Through the Reflection delegation this allows you to communicate commands between ClassLoaders. + * * @see ApiClassloadingHelper */ @Data public class ClAgnosticCommand implements Command { + /** + * A remote instance of {@link Command}, potentially loaded by another classloader. + * Because of that we cannot cast it to a Command directly, + * but need to use reflection to access its methods. + */ private final Object delegate; @Override diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommandContext.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommandContext.java index 521fc0d9..6a695db3 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommandContext.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/classloading/ClAgnosticCommandContext.java @@ -14,13 +14,17 @@ import java.util.Map; /** + * A {@link CommandContext} implementation that delegates to another CommandContext. + * This delegation happens via reflection so any object that exposes the same methods as {@link CommandContext} can be used. + * This is generally meant for environments where the CommandContext class has been loaded multiple times from multiple ClassLoaders. + * Through the Reflection delegation this allows you to communicate commands between ClassLoaders. * * @see ApiClassloadingHelper */ @Data public class ClAgnosticCommandContext implements CommandContext { /** - * A remote instance of {@link CommandLine}, loaded by another classloader. + * A remote instance of {@link CommandLine}, potentially loaded by another classloader. * Because of that we cannot cast it to a CommandContext directly, * but need to use reflection to access its methods. * This CommandContext delegates to the commandContext provided by this command line. diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/AbstractCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/AbstractCommand.java index 6eb17b73..5d49bb74 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/AbstractCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/AbstractCommand.java @@ -8,6 +8,9 @@ import java.util.LinkedHashMap; import java.util.Map; +/** + * Abstract base class for {@link Command}. + */ @EqualsAndHashCode @RequiredArgsConstructor public abstract class AbstractCommand implements Command { diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/Command.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/Command.java index 3f5ccf06..3413364b 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/Command.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/Command.java @@ -14,6 +14,8 @@ * Commands are managed by a {@link CommandContext}. * Due to classloading problems, Commands and CommandContext both only expose methods * where parameters and return values are from the java packages (see {@link ApiClassloadingHelper}). + * + * @see AbstractCommand */ public interface Command extends HasName, HasDescription, HasArguments { /** diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandContextImpl.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandContextImpl.java index d1e1afa3..84935c8b 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandContextImpl.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandContextImpl.java @@ -3,15 +3,25 @@ import lombok.RequiredArgsConstructor; import lombok.val; import me.earth.headlessmc.api.HeadlessMc; +import me.earth.headlessmc.api.LogsMessages; import me.earth.headlessmc.api.config.HmcProperties; import org.jetbrains.annotations.NotNull; import java.util.*; +/** + * Default implementation of {@link CommandContext}. + */ @RequiredArgsConstructor @SuppressWarnings({"unchecked", "RedundantSuppression"}) // delegate public class CommandContextImpl implements CommandContext { + /** + * The list of Commands that this CommandContext can execute. + */ protected final List commands = new ArrayList<>(); + /** + * The HeadlessMc instance this CommandContext uses for {@link LogsMessages#log(String)}. + */ protected final HeadlessMc log; @Override @@ -31,6 +41,14 @@ public void execute(String message) { } } + /** + * Calls {@link Command#execute(String, String...)} on the given command for the given Arguments. + * Catches any {@link CommandException} that might occur and logs it. + * + * @param cmd the command to execute. + * @param message the full command. + * @param args the message split into arguments. + */ protected void executeCommand(Command cmd, String message, String... args) { try { cmd.execute(message, args); diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandException.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandException.java index 2d9398ed..ac35851b 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandException.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/CommandException.java @@ -9,6 +9,14 @@ */ @StandardException public class CommandException extends Exception { + /** + * Constructs a new CommandException with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ public CommandException(String message) { super(message); } diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/HelpCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/HelpCommand.java index 7aad60d8..5e610419 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/HelpCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/HelpCommand.java @@ -2,15 +2,23 @@ import me.earth.headlessmc.api.HasName; import me.earth.headlessmc.api.HeadlessMc; -import me.earth.headlessmc.api.command.AbstractCommand; -import me.earth.headlessmc.api.command.Command; -import me.earth.headlessmc.api.command.CommandException; -import me.earth.headlessmc.api.command.HasDescription; +import me.earth.headlessmc.api.command.*; +import me.earth.headlessmc.api.command.line.CommandLine; import me.earth.headlessmc.api.util.Table; import java.util.Map; +/** + * A {@link Command} implementation that displays information about Commands from a {@link CommandContext}. + */ public class HelpCommand extends AbstractCommand { + /** + * Constructs a new HelpCommand. + * The {@link CommandContext} from the {@link CommandLine} of the given {@link HeadlessMc} + * will be used to list commands and to find commands to display information for. + * + * @param ctx the HeadlessMc instance holding the CommandLine with the commands. + */ public HelpCommand(HeadlessMc ctx) { super(ctx, "help", "Information about commands."); args.put("", "The name of the command to get help for."); @@ -25,25 +33,22 @@ public void execute(String line, String... args) throws CommandException { if (args.length > 2) { String desc = cmd.getArgDescription(args[2]); if (desc == null) { - throw new CommandException( - "No description found for '" + args[2] + "'."); + throw new CommandException("No description found for '" + args[2] + "'."); } else { - ctx.log(String.format( - "%s %s: %s", cmd.getName(), args[2], desc)); + ctx.log(String.format("%s %s: %s", cmd.getName(), args[2], desc)); } } else { - ctx.log(String.format("%s : %s", cmd.getName(), - cmd.getDescription())); + ctx.log(String.format("%s : %s", cmd.getName(), cmd.getDescription())); ctx.log( new Table>() .withColumn("arg", Map.Entry::getKey) .withColumn("description", Map.Entry::getValue) .addAll(cmd.getArgs2Descriptions()) - .build()); + .build() + ); } } else { - throw new CommandException( - String.format("Couldn't find command %s", args[1])); + throw new CommandException(String.format("Couldn't find command %s", args[1])); } } else { ctx.log( @@ -52,7 +57,8 @@ public void execute(String line, String... args) throws CommandException { .withColumn("description", HasDescription::getDescription) .withColumn("args", this::argsToString) .addAll(ctx.getCommandLine().getCommandContext()) - .build()); + .build() + ); } } diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MemoryCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MemoryCommand.java index a4c87438..7557781f 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MemoryCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MemoryCommand.java @@ -2,12 +2,17 @@ import lombok.val; import me.earth.headlessmc.api.HeadlessMc; +import me.earth.headlessmc.api.LogsMessages; import me.earth.headlessmc.api.command.AbstractCommand; +import me.earth.headlessmc.api.command.Command; import me.earth.headlessmc.api.command.CommandException; import java.math.RoundingMode; import java.text.DecimalFormat; +/** + * A {@link Command} implementation that displays the currently used memory, free memory and max memory of the JVM. + */ public class MemoryCommand extends AbstractCommand { private static final DecimalFormat DF = new DecimalFormat("#.##"); @@ -15,6 +20,11 @@ public class MemoryCommand extends AbstractCommand { DF.setRoundingMode(RoundingMode.CEILING); } + /** + * Constructs a new MemoryCommand instance. + * + * @param ctx the {@link LogsMessages} used to log the output. + */ public MemoryCommand(HeadlessMc ctx) { super(ctx, "memory", "Displays Memory stats."); } diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MultiCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MultiCommand.java index e489071b..d2058655 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MultiCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/MultiCommand.java @@ -2,9 +2,24 @@ import me.earth.headlessmc.api.HeadlessMc; import me.earth.headlessmc.api.command.AbstractCommand; +import me.earth.headlessmc.api.command.Command; import me.earth.headlessmc.api.command.CommandException; +import me.earth.headlessmc.api.command.QuickExitCli; +import me.earth.headlessmc.api.command.line.CommandLine; +/** + * A {@link Command} that treats its given arguments as commands and executes them. + * This is useful when you want to start HeadlessMc with the {@link QuickExitCli} + * from the command line; and you want to execute multiple commands that you know beforehand. + */ public class MultiCommand extends AbstractCommand { + /** + * Constructs a new MultiCommand command. + * The {@link CommandLine} of the given {@link HeadlessMc} instance + * will be used to execute the given commands. + * + * @param ctx the HeadlessMc instance supplying the {@link CommandLine} to execute commands on. + */ public MultiCommand(HeadlessMc ctx) { super(ctx, "multi", "Run multiple commands together."); args.put("", "The commands to run."); diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/QuitCommand.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/QuitCommand.java index a5446c43..d1008367 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/QuitCommand.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/impl/QuitCommand.java @@ -2,10 +2,20 @@ import me.earth.headlessmc.api.HeadlessMc; import me.earth.headlessmc.api.command.AbstractCommand; +import me.earth.headlessmc.api.command.Command; +import me.earth.headlessmc.api.exit.ExitManager; import java.util.Locale; +/** + * A {@link Command} that calls HeadlessMc's {@link ExitManager} to quit the process. + */ public class QuitCommand extends AbstractCommand { + /** + * Constructs a new QuitCommand. + * + * @param ctx the HeadlessMc instance to get the {@link ExitManager} from. + */ public QuitCommand(HeadlessMc ctx) { super(ctx, "quit", "Quits HeadlessMc."); } diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/BufferedCommandLineReader.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/BufferedCommandLineReader.java index 73bf7708..661dc018 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/BufferedCommandLineReader.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/BufferedCommandLineReader.java @@ -2,12 +2,17 @@ import lombok.CustomLog; import me.earth.headlessmc.api.HeadlessMc; +import me.earth.headlessmc.api.process.InAndOutProvider; import java.io.BufferedReader; import java.io.IOError; import java.io.IOException; import java.io.InputStreamReader; +/** + * The simplest {@link CommandLineReader} implementation, + * which reads {@link InAndOutProvider#getIn()} with a {@link BufferedReader}. + */ @CustomLog public class BufferedCommandLineReader implements CommandLineReader { @Override diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/ConsoleCommandLineReader.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/ConsoleCommandLineReader.java index fef8144a..4c3b8b8b 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/ConsoleCommandLineReader.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/ConsoleCommandLineReader.java @@ -3,10 +3,15 @@ import lombok.CustomLog; import lombok.RequiredArgsConstructor; import me.earth.headlessmc.api.HeadlessMc; +import me.earth.headlessmc.api.process.InAndOutProvider; import java.io.Console; import java.io.IOError; +/** + * An implementation of {@link CommandLineReader} that reads from the console supplied by {@link InAndOutProvider#getConsole()}. + * This is usually {@link System#console()}. + */ @CustomLog @RequiredArgsConstructor class ConsoleCommandLineReader implements CommandLineReader { diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/DefaultCommandLineProvider.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/DefaultCommandLineProvider.java index 22d78da3..6c428594 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/DefaultCommandLineProvider.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/DefaultCommandLineProvider.java @@ -7,6 +7,13 @@ import java.io.Console; import java.util.function.Supplier; +/** + * A {@link CommandLineReader} that decides whether to use a {@link BufferedCommandLineReader} or a {@link ConsoleCommandLineReader}. + * If the {@link InAndOutProvider#getConsole()} is available a {@link ConsoleCommandLineReader} will be used always. + * + * @see BufferedCommandLineReader + * @see ConsoleCommandLineReader + */ @CustomLog @RequiredArgsConstructor public class DefaultCommandLineProvider implements Supplier { diff --git a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/PasswordAwareImpl.java b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/PasswordAwareImpl.java index 11fca1ce..6279c598 100644 --- a/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/PasswordAwareImpl.java +++ b/headlessmc-api/src/main/java/me/earth/headlessmc/api/command/line/PasswordAwareImpl.java @@ -4,6 +4,9 @@ import lombok.Setter; import me.earth.headlessmc.api.command.PasswordAware; +/** + * Simplest implementation of {@link PasswordAware}. + */ @Getter @Setter public class PasswordAwareImpl implements PasswordAware { diff --git a/headlessmc-auth/src/main/java/me/earth/headlessmc/auth/AuthProperties.java b/headlessmc-auth/src/main/java/me/earth/headlessmc/auth/AuthProperties.java deleted file mode 100644 index 593aae01..00000000 --- a/headlessmc-auth/src/main/java/me/earth/headlessmc/auth/AuthProperties.java +++ /dev/null @@ -1,12 +0,0 @@ -package me.earth.headlessmc.auth; - -import me.earth.headlessmc.api.config.Property; - -import static me.earth.headlessmc.api.config.PropertyTypes.bool; -import static me.earth.headlessmc.api.config.PropertyTypes.string; - -public interface AuthProperties { - Property WEBVIEW_DEVICE_TOKEN = string("hmc.auth.webview.device.token"); - Property WEBVIEW_NO_DEVICE_TOKEN = bool("hmc.auth.webview.no.device.token"); - -} diff --git a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/CommandCompleter.java b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/CommandCompleter.java index 51271e90..796a7c4f 100644 --- a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/CommandCompleter.java +++ b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/CommandCompleter.java @@ -2,6 +2,7 @@ import lombok.RequiredArgsConstructor; import me.earth.headlessmc.api.HeadlessMc; +import me.earth.headlessmc.api.command.CommandContext; import org.jetbrains.annotations.Nullable; import org.jline.reader.Candidate; import org.jline.reader.Completer; @@ -11,6 +12,9 @@ import java.util.List; import java.util.Map; +/** + * A JLine {@link Completer} that completes a given command with the current {@link CommandContext}. + */ @RequiredArgsConstructor public class CommandCompleter implements Completer { private final HeadlessMc hmc; diff --git a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineCommandLineReader.java b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineCommandLineReader.java index bb4153b1..ee6b257c 100644 --- a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineCommandLineReader.java +++ b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineCommandLineReader.java @@ -20,14 +20,32 @@ import java.io.IOException; import java.util.function.BiConsumer; +/** + * An implementation of a {@link CommandLineReader} that reads commands from a JLine {@link Terminal} with a {@link LineReader}. + */ @Getter @CustomLog public class JLineCommandLineReader implements CommandLineReader { + /** + * The prefix to display when reading from the command line. + */ @Setter protected volatile String readPrefix; - protected volatile LineReader lineReader; - protected volatile Terminal terminal; + /** + * The LineReader we are currently reading from. + * Might be {@code null}. + */ + protected volatile @Nullable LineReader lineReader; + /** + * The Terminal that is currently in use. + * Might be {@code null}. + */ + protected volatile @Nullable Terminal terminal; + /** + * If the {@link #terminal} in use is a dumb terminal. + * @see TerminalBuilder#dumb(boolean) + */ protected volatile boolean dumb; @Override diff --git a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineProperties.java b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineProperties.java index 230410e0..adbc5fce 100644 --- a/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineProperties.java +++ b/headlessmc-jline/src/main/java/me/earth/headlessmc/jline/JLineProperties.java @@ -3,6 +3,9 @@ import me.earth.headlessmc.api.config.Property; import me.earth.headlessmc.api.config.PropertyTypes; +/** + * A collection of properties for configuring JLine. + */ public interface JLineProperties { Property ENABLED = PropertyTypes.bool("hmc.jline.enabled");