diff --git a/.gitignore b/.gitignore index 7d126a0..0109f9c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .idea/ .gradle/ .settings/ +.vscode/ #build /build/ diff --git a/build.gradle b/build.gradle index bdfcad0..93d1e02 100644 --- a/build.gradle +++ b/build.gradle @@ -4,19 +4,22 @@ plugins { id 'maven-publish' } +repositories { + mavenCentral() +} + group 'cc.sukazyo' version PROJECT_VERSION project.ext.archiveBaseName = 'messiva' project.ext.artifactId = 'messiva' -repositories { - mavenCentral() -} - dependencies { compileOnlyApi "com.github.spotbugs:spotbugs-annotations:${libSpotbugsVersion}" + implementation "org.jline:jline:${libJLineVersion}" + implementation "org.fusesource.jansi:jansi:${libJansiVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-api:${libJUnitVersion}" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${libJUnitVersion}" @@ -35,11 +38,11 @@ java { } -tasks.withType(JavaCompile) { +tasks.withType(JavaCompile).configureEach { options.encoding = "UTF-8" } -tasks.withType(Javadoc) { +tasks.withType(Javadoc).configureEach { options.encoding = 'UTF-8' options.docEncoding = 'UTF-8' options.charSet = 'UTF-8' diff --git a/gradle.properties b/gradle.properties index 4dc4de0..21dd394 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,12 @@ ## Messiva -PROJECT_VERSION = 0.1.0.1 +PROJECT_VERSION = 0.1.1 ## dependencies libSpotbugsVersion = 4.5.0 +libJLineVersion = 3.21.0 +libJansiVersion = 2.4.0 + libJUnitVersion = 5.8.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 84d1f85..e1bef7e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/main/java/cc/sukazyo/messiva/appender/Appender.java b/src/main/java/cc/sukazyo/messiva/appender/Appender.java new file mode 100644 index 0000000..e738f15 --- /dev/null +++ b/src/main/java/cc/sukazyo/messiva/appender/Appender.java @@ -0,0 +1,26 @@ +package cc.sukazyo.messiva.appender; + +import cc.sukazyo.messiva.formatter.ILogFormatter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class Appender implements IAppender { + + @Nullable public ILogFormatter formatter; + + public Appender (@Nullable ILogFormatter formatter) { + this.formatter = formatter; + } + + public Appender () { + this(null); + } + + @Nonnull + public Appender setFormatter (@Nullable ILogFormatter formatter) { + this.formatter = formatter; + return this; + } + +} diff --git a/src/main/java/cc/sukazyo/messiva/appender/AppenderRestrictableByLevel.java b/src/main/java/cc/sukazyo/messiva/appender/AppenderRestrictableByLevel.java new file mode 100644 index 0000000..167c3da --- /dev/null +++ b/src/main/java/cc/sukazyo/messiva/appender/AppenderRestrictableByLevel.java @@ -0,0 +1,43 @@ +package cc.sukazyo.messiva.appender; + +import cc.sukazyo.messiva.component.LevelRestrictComponent; +import cc.sukazyo.messiva.formatter.ILogFormatter; +import cc.sukazyo.messiva.log.Log; +import cc.sukazyo.messiva.log.LogLevel; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public abstract class AppenderRestrictableByLevel extends Appender { + + @Nonnull public LevelRestrictComponent levelSetting; + + public AppenderRestrictableByLevel (@Nullable ILogFormatter formatter) { + super(formatter); + levelSetting = new LevelRestrictComponent(); + } + + public AppenderRestrictableByLevel () { + this(null); + } + + @Nonnull + public AppenderRestrictableByLevel minLevel(@Nonnull LogLevel minLevel) { + levelSetting.minLevel(minLevel); + return this; + } + + @Nonnull + public AppenderRestrictableByLevel maxLevel(@Nonnull LogLevel maxLevel) { + levelSetting.maxLevel(maxLevel); + return this; + } + + public void pushLog (@Nonnull Log log) { + if (!levelSetting.checkLevel(log.level)) return; + pushLogChecked(log); + } + + abstract public void pushLogChecked (@Nonnull Log log); + +} diff --git a/src/main/java/cc/sukazyo/messiva/appender/ConsoleAppender.java b/src/main/java/cc/sukazyo/messiva/appender/ConsoleAppender.java index af6e982..55ea206 100644 --- a/src/main/java/cc/sukazyo/messiva/appender/ConsoleAppender.java +++ b/src/main/java/cc/sukazyo/messiva/appender/ConsoleAppender.java @@ -1,46 +1,32 @@ package cc.sukazyo.messiva.appender; +import cc.sukazyo.messiva.formatter.ILogFormatter; import cc.sukazyo.messiva.log.Log; import cc.sukazyo.messiva.utils.StringUtils; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.concurrent.locks.ReentrantLock; -public class ConsoleAppender implements IAppender { +public class ConsoleAppender extends AppenderRestrictableByLevel { - private final ReentrantLock syncLock = new ReentrantLock(); + @Nonnull private final ReentrantLock syncLock; -// private final AppendDaemon DAEMON; -// private static class AppendDaemon extends Thread { -// public AppendDaemon () { this.setName("console-appender-daemon::" + UUID.randomUUID()); } -// @Override public void run () { -// -// } -// } -// - public ConsoleAppender() { -// DAEMON = new AppendDaemon(); -// DAEMON.start(); + public ConsoleAppender (@Nullable ILogFormatter formatter) { + super(formatter); + syncLock = new ReentrantLock(); + } + + public ConsoleAppender () { + this(null); } @Override - public void pushLog (Log log) { + public void pushLogChecked (@Nonnull Log log) { + if (formatter == null) return; syncLock.lock(); - System.out.println(formatMessage(log)); + System.out.println(formatter.format(log)); syncLock.unlock(); } - private static String formatMessage (Log log) { - final StringBuilder message = new StringBuilder(); - message.append('[').append(log.timestamp) - .append("][").append(log.thread.getName()) - .append("]"); - final String promptNewline = StringUtils.repeatChar('\'', message.length()); - message.append('[').append(log.level.tag).append(']').append(log.message.message[0]); - for (int i = 1; i < log.message.message.length; i++) { - message.append('\n').append(promptNewline) - .append('[').append(log.level.tag).append(']').append(log.message.message[i]); - } - return message.toString(); - } - } diff --git a/src/main/java/cc/sukazyo/messiva/component/LevelRestrictComponent.java b/src/main/java/cc/sukazyo/messiva/component/LevelRestrictComponent.java new file mode 100644 index 0000000..e6ba341 --- /dev/null +++ b/src/main/java/cc/sukazyo/messiva/component/LevelRestrictComponent.java @@ -0,0 +1,51 @@ +package cc.sukazyo.messiva.component; + +import cc.sukazyo.messiva.log.LogLevel; + +import javax.annotation.Nonnull; + +public class LevelRestrictComponent { + + @Nonnull private LogLevel minLevel; + @Nonnull private LogLevel maxLevel; + + public LevelRestrictComponent (@Nonnull LogLevel minLevel, @Nonnull LogLevel maxLevel) { + this.minLevel = minLevel; + this.maxLevel = maxLevel; + } + + public LevelRestrictComponent (@Nonnull LogLevel minLevel) { + this(minLevel, LogLevel.NONE); + } + + public LevelRestrictComponent () { + this(LogLevel.ALL); + } + + @Nonnull + public LevelRestrictComponent minLevel (@Nonnull LogLevel minLevel) { + this.minLevel = minLevel; + return this; + } + + @Nonnull + public LevelRestrictComponent maxLevel (@Nonnull LogLevel maxLevel) { + this.maxLevel = maxLevel; + return this; + } + + @Nonnull + public LogLevel minLevel () { + return this.minLevel; + } + + @Nonnull + public LogLevel maxLevel () { + return this.maxLevel; + } + + public boolean checkLevel (@Nonnull LogLevel level) { + return level.level >= minLevel.level && level.level <= maxLevel.level; + } + +} diff --git a/src/main/java/cc/sukazyo/messiva/formatter/ILogFormatter.java b/src/main/java/cc/sukazyo/messiva/formatter/ILogFormatter.java new file mode 100644 index 0000000..843b70d --- /dev/null +++ b/src/main/java/cc/sukazyo/messiva/formatter/ILogFormatter.java @@ -0,0 +1,12 @@ +package cc.sukazyo.messiva.formatter; + +import cc.sukazyo.messiva.log.Log; + +import javax.annotation.Nonnull; + +public interface ILogFormatter { + + @Nonnull + String format(@Nonnull Log log); + +} diff --git a/src/main/java/cc/sukazyo/messiva/formatter/SimpleFormatter.java b/src/main/java/cc/sukazyo/messiva/formatter/SimpleFormatter.java new file mode 100644 index 0000000..8a955cd --- /dev/null +++ b/src/main/java/cc/sukazyo/messiva/formatter/SimpleFormatter.java @@ -0,0 +1,33 @@ +package cc.sukazyo.messiva.formatter; + +import cc.sukazyo.messiva.log.Log; +import cc.sukazyo.messiva.utils.StringUtils; + +import javax.annotation.Nonnull; + +public class SimpleFormatter implements ILogFormatter { + + @Nonnull public String startTimestamp = "["; + @Nonnull public String endTimestamp = "]"; + @Nonnull public String startThreadName = "["; + @Nonnull public String endThreadName = "]"; + @Nonnull public String startLevelTag = "["; + @Nonnull public String endLevelTag = "]"; + public char followingLineFillChar = '\''; + + @Nonnull + @Override + public String format (@Nonnull Log log) { + final StringBuilder message = new StringBuilder(); + message.append(startTimestamp).append(log.timestamp).append(endTimestamp) + .append(startThreadName).append(log.thread.getName()).append(endThreadName); + final String promptNewline = StringUtils.repeatChar(followingLineFillChar, message.length()); + message.append(startLevelTag).append(log.level.tag).append(endLevelTag).append(log.message.message[0]); + for (int i = 1; i < log.message.message.length; i++) { + message.append('\n').append(promptNewline) + .append(startLevelTag).append(log.level.tag).append(endLevelTag).append(log.message.message[i]); + } + return message.toString(); + } + +} diff --git a/src/main/java/cc/sukazyo/messiva/log/ILogLevelImpl.java b/src/main/java/cc/sukazyo/messiva/log/ILogLevelImpl.java index 7921b26..9f94106 100644 --- a/src/main/java/cc/sukazyo/messiva/log/ILogLevelImpl.java +++ b/src/main/java/cc/sukazyo/messiva/log/ILogLevelImpl.java @@ -10,6 +10,8 @@ public interface ILogLevelImpl { void warn (String message); + void warning (String message); + void error (String message); void fatal (String message); diff --git a/src/main/java/cc/sukazyo/messiva/log/LogLevel.java b/src/main/java/cc/sukazyo/messiva/log/LogLevel.java index bbdf42a..efe5ada 100644 --- a/src/main/java/cc/sukazyo/messiva/log/LogLevel.java +++ b/src/main/java/cc/sukazyo/messiva/log/LogLevel.java @@ -2,12 +2,14 @@ package cc.sukazyo.messiva.log; public enum LogLevel { - TRACE(-1f, "TRAC"), - DEBUG(-0.1f, "DBUG"), - INFO(0f, "INFO"), - WARN(0.5f, "WARN"), - ERROR(1f, "ERRO"), - FATAL(10f, "FTAL"); + ALL (-Float.MAX_VALUE, "####"), + TRACE(-1f, "TRAC"), + DEBUG(-0.1f, "DBUG"), + INFO (0f, "INFO"), + WARN (0.5f, "WARN"), + ERROR(1f, "ERRO"), + FATAL(10f, "FTAL"), + NONE(Float.MAX_VALUE, "!!!!"); public final float level; public final String tag; diff --git a/src/main/java/cc/sukazyo/messiva/log/Message.java b/src/main/java/cc/sukazyo/messiva/log/Message.java index 7830751..c51b725 100644 --- a/src/main/java/cc/sukazyo/messiva/log/Message.java +++ b/src/main/java/cc/sukazyo/messiva/log/Message.java @@ -5,7 +5,7 @@ public class Message { public final String[] message; public Message(String message) { - this.message = message.split("\n"); + this.message = message == null ? new String[]{} : message.split("\n"); } } diff --git a/src/main/java/cc/sukazyo/messiva/Logger.java b/src/main/java/cc/sukazyo/messiva/logger/Logger.java similarity index 66% rename from src/main/java/cc/sukazyo/messiva/Logger.java rename to src/main/java/cc/sukazyo/messiva/logger/Logger.java index ab406b5..e8b56aa 100644 --- a/src/main/java/cc/sukazyo/messiva/Logger.java +++ b/src/main/java/cc/sukazyo/messiva/logger/Logger.java @@ -1,25 +1,43 @@ -package cc.sukazyo.messiva; +package cc.sukazyo.messiva.logger; +import cc.sukazyo.messiva.component.LevelRestrictComponent; import cc.sukazyo.messiva.appender.IAppender; import cc.sukazyo.messiva.log.ILogLevelImpl; import cc.sukazyo.messiva.log.Log; import cc.sukazyo.messiva.log.LogLevel; import cc.sukazyo.messiva.log.Message; +import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class Logger implements ILogLevelImpl { - public final List appends = new ArrayList<>(); + @Nonnull public final List appends; - public Logger () {} + @Nonnull public LevelRestrictComponent levelSetting; + + public Logger () { + levelSetting = new LevelRestrictComponent(); + appends = new ArrayList<>(); + } public Logger (IAppender... appends) { + this(); this.appends.addAll(Arrays.asList(appends)); } + public Logger minLevel (@Nonnull LogLevel minLevel) { + levelSetting.minLevel(minLevel); + return this; + } + + public Logger maxLevel (@Nonnull LogLevel maxLevel) { + levelSetting.maxLevel(maxLevel); + return this; + } + public void trace (String message) { pushToAllAppender(new Log(1, new Message(message), LogLevel.TRACE)); } @@ -48,7 +66,8 @@ public class Logger implements ILogLevelImpl { pushToAllAppender(new Log(1, new Message(message), LogLevel.FATAL)); } - private void pushToAllAppender (Log log) { + private void pushToAllAppender (@Nonnull Log log) { + if (!levelSetting.checkLevel(log.level)) return; for (IAppender appender : appends) { appender.pushLog(log); }