From bc51e533540464f811657dc5e967047a237f01ad Mon Sep 17 00:00:00 2001 From: yangkui <752544765@qq.com> Date: Thu, 12 Jan 2023 22:27:53 +0800 Subject: [PATCH] Switch log from slf4j to java logging --- app/pom.xml | 13 +--- .../main/java/cn/navclub/nes4j/app/INes.java | 3 +- .../java/cn/navclub/nes4j/app/Launcher.java | 4 + .../cn/navclub/nes4j/app/util/StrUtil.java | 3 - .../cn/navclub/nes4j/app/view/GameHall.java | 20 ++++- app/src/main/java/module-info.java | 3 - .../nes4j/app/assets/css/GameHallStyle.css | 1 + .../nes4j/app/assets/fxml/GameHall.fxml | 7 +- .../cn/navclub/nes4j/app/assets/img/nes4j.png | Bin 0 -> 34233 bytes app/src/main/resources/logback.xml | 35 --------- bin/pom.xml | 17 ----- .../main/java/cn/navclub/nes4j/bin/NES.java | 6 -- .../navclub/nes4j/bin/apu/FrameCounter.java | 1 - .../navclub/nes4j/bin/config/Instruction.java | 1 - .../java/cn/navclub/nes4j/bin/core/Bus.java | 4 - .../java/cn/navclub/nes4j/bin/core/CPU.java | 9 ++- .../java/cn/navclub/nes4j/bin/log/Level.java | 17 +++++ .../java/cn/navclub/nes4j/bin/log/Logger.java | 42 ++++++++++ .../navclub/nes4j/bin/log/LoggerAdapter.java | 20 +++++ .../nes4j/bin/log/formatter/NFormatter.java | 72 ++++++++++++++++++ .../navclub/nes4j/bin/log/impl/NLogger.java | 55 +++++++++++++ .../nes4j/bin/ppu/register/PPUControl.java | 2 +- bin/src/main/java/module-info.java | 4 +- pom.xml | 15 ---- 24 files changed, 242 insertions(+), 112 deletions(-) create mode 100644 app/src/main/resources/cn/navclub/nes4j/app/assets/img/nes4j.png delete mode 100644 app/src/main/resources/logback.xml create mode 100644 bin/src/main/java/cn/navclub/nes4j/bin/log/Level.java create mode 100644 bin/src/main/java/cn/navclub/nes4j/bin/log/Logger.java create mode 100644 bin/src/main/java/cn/navclub/nes4j/bin/log/LoggerAdapter.java create mode 100644 bin/src/main/java/cn/navclub/nes4j/bin/log/formatter/NFormatter.java create mode 100644 bin/src/main/java/cn/navclub/nes4j/bin/log/impl/NLogger.java diff --git a/app/pom.xml b/app/pom.xml index 5ec0705..49c6f6e 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -51,18 +51,7 @@ nes4j-bin 1.0.1 - - org.slf4j - slf4j-api - - - ch.qos.logback - logback-core - - - ch.qos.logback - logback-classic - + com.fasterxml.jackson.core jackson-core diff --git a/app/src/main/java/cn/navclub/nes4j/app/INes.java b/app/src/main/java/cn/navclub/nes4j/app/INes.java index 9c27837..445964b 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/INes.java +++ b/app/src/main/java/cn/navclub/nes4j/app/INes.java @@ -7,11 +7,10 @@ import javafx.application.Application; import javafx.stage.Stage; -import lombok.extern.slf4j.Slf4j; + import java.util.ResourceBundle; -@Slf4j public class INes extends Application { public final static EventBus eventBus; public static final ResourceBundle RESOURCE_BUNDLE; diff --git a/app/src/main/java/cn/navclub/nes4j/app/Launcher.java b/app/src/main/java/cn/navclub/nes4j/app/Launcher.java index b8afdcd..139c648 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/Launcher.java +++ b/app/src/main/java/cn/navclub/nes4j/app/Launcher.java @@ -3,12 +3,16 @@ import cn.navclub.nes4j.app.config.NESConfig; import cn.navclub.nes4j.app.util.JsonUtil; import cn.navclub.nes4j.app.util.StrUtil; +import cn.navclub.nes4j.bin.log.Logger; +import cn.navclub.nes4j.bin.log.LoggerAdapter; import javafx.application.Application; import java.nio.file.Files; import java.nio.file.Path; public class Launcher { + + private static final Logger logger = LoggerAdapter.logger(Launcher.class); private static final String DEFAULT_CONFIG_PATH = "config/config.json"; public static void main(String[] args) throws Exception { diff --git a/app/src/main/java/cn/navclub/nes4j/app/util/StrUtil.java b/app/src/main/java/cn/navclub/nes4j/app/util/StrUtil.java index 3dd66a7..1c3cf69 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/util/StrUtil.java +++ b/app/src/main/java/cn/navclub/nes4j/app/util/StrUtil.java @@ -1,12 +1,9 @@ package cn.navclub.nes4j.app.util; -import lombok.extern.slf4j.Slf4j; - import java.io.File; import java.util.HashMap; import java.util.Map; -@Slf4j public class StrUtil { /** * 获取文件名称且移除后缀 diff --git a/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java b/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java index 44f764c..b2afffb 100644 --- a/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java +++ b/app/src/main/java/cn/navclub/nes4j/app/view/GameHall.java @@ -13,6 +13,7 @@ import javafx.scene.Scene; import javafx.scene.control.ListView; import javafx.scene.layout.FlowPane; +import javafx.scene.paint.Color; import javafx.stage.Stage; import javafx.stage.StageStyle; @@ -20,6 +21,7 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import java.util.TimeZone; /** * Visible Game wall @@ -44,12 +46,14 @@ public GameHall(Stage stage) { this.gameWorld = new GameWorld(); Scene scene = new Scene(FXResource.loadFXML(this)); + this.stage = stage; this.stage.setWidth(1200); this.stage.setHeight(900); - this.stage.setTitle("ines"); + this.stage.setTitle("nes4j"); this.stage.setScene(scene); this.stage.initStyle(StageStyle.UNDECORATED); + this.stage.getIcons().add(FXResource.loadImage("nes4j.png")); this.stage.show(); this.loadAssort(); @@ -117,9 +121,21 @@ protected List call() { }; } + /** + *

+ * Open current project open source address.If user location in China will visit gitee, + * otherwise visit github.

+ */ @FXML public void github() { - INes.eventBus.publish(EventBusAddress.OPEN_URI, "https://github.com/GZYangKui/nes4j"); + final String uri; + var tid = TimeZone.getDefault().getID(); + if (tid.toLowerCase().contains("shanghai")) { + uri = "https://gitee.com/navigatorcode/nes4j"; + } else { + uri = "https://github.com/GZYangKui/nes4j"; + } + INes.eventBus.publish(EventBusAddress.OPEN_URI, uri); } @FXML diff --git a/app/src/main/java/module-info.java b/app/src/main/java/module-info.java index 1724699..ef3daca 100644 --- a/app/src/main/java/module-info.java +++ b/app/src/main/java/module-info.java @@ -12,9 +12,6 @@ requires cn.navclub.nes4j.bin; requires org.controlsfx.controls; - requires org.slf4j; - requires ch.qos.logback.core; - requires ch.qos.logback.classic; requires com.fasterxml.jackson.core; requires com.fasterxml.jackson.databind; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css index bcc5d23..82df416 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/css/GameHallStyle.css @@ -1,5 +1,6 @@ @import "common.css"; + .navbar *, .assort, .flow-pane .game-tray .label, .empty .label { -fx-font-size: 1.4em; -fx-text-fill: -nes4j-game-hall-text-fill; diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameHall.fxml b/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameHall.fxml index 4fcd73b..f5da7c6 100644 --- a/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameHall.fxml +++ b/app/src/main/resources/cn/navclub/nes4j/app/assets/fxml/GameHall.fxml @@ -16,7 +16,7 @@ - + @@ -29,11 +29,6 @@ - diff --git a/app/src/main/resources/cn/navclub/nes4j/app/assets/img/nes4j.png b/app/src/main/resources/cn/navclub/nes4j/app/assets/img/nes4j.png new file mode 100644 index 0000000000000000000000000000000000000000..e2b5ef83427d911221f083af9faa8099c2816db9 GIT binary patch literal 34233 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 Rw^|VRNr}me77H7E{2%Hj98UlM literal 0 HcmV?d00001 diff --git a/app/src/main/resources/logback.xml b/app/src/main/resources/logback.xml deleted file mode 100644 index c24f7d7..0000000 --- a/app/src/main/resources/logback.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - ${LOG_PATTERN} - - - - - ${LOG_HOME} - - - ${LOG_HOME}.%d{yyyy-MM-dd}.%i - 30 - 50MB - - - ${LOG_PATTERN} - - - - - - - - - - \ No newline at end of file diff --git a/bin/pom.xml b/bin/pom.xml index 9472087..11a483d 100644 --- a/bin/pom.xml +++ b/bin/pom.xml @@ -34,23 +34,6 @@ - - - - org.slf4j - slf4j-api - - - ch.qos.logback - logback-core - test - - - ch.qos.logback - logback-classic - test - - diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/NES.java b/bin/src/main/java/cn/navclub/nes4j/bin/NES.java index 0287bd1..44aa9a5 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/NES.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/NES.java @@ -3,8 +3,6 @@ import cn.navclub.nes4j.bin.apu.APU; import cn.navclub.nes4j.bin.apu.Player; import cn.navclub.nes4j.bin.core.*; -import cn.navclub.nes4j.bin.core.impl.NRMapper; -import cn.navclub.nes4j.bin.core.impl.UXMapper; import cn.navclub.nes4j.bin.debug.Debugger; import cn.navclub.nes4j.bin.config.CPUInterrupt; import cn.navclub.nes4j.bin.eventbus.EventBus; @@ -15,15 +13,11 @@ import cn.navclub.nes4j.bin.ppu.PPU; import lombok.Getter; import lombok.Setter; -import lombok.extern.slf4j.Slf4j; import java.io.File; -import java.util.Queue; -import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.CompletableFuture; import java.util.concurrent.locks.LockSupport; -@Slf4j @Getter public class NES { private final Bus bus; diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/apu/FrameCounter.java b/bin/src/main/java/cn/navclub/nes4j/bin/apu/FrameCounter.java index 1af7028..2267548 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/apu/FrameCounter.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/apu/FrameCounter.java @@ -26,7 +26,6 @@ * * @author GZYangKui */ -@Slf4j public class FrameCounter implements Component { /** diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java b/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java index da5fe6c..7dd4dc4 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/config/Instruction.java @@ -13,7 +13,6 @@ * * @author GZYangKui */ -@Slf4j public enum Instruction { /** * More detail please visit:ADC Document diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java b/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java index 0a5f13b..151c557 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/core/Bus.java @@ -2,12 +2,9 @@ import cn.navclub.nes4j.bin.NES; import cn.navclub.nes4j.bin.apu.APU; -import cn.navclub.nes4j.bin.config.NMapper; -import cn.navclub.nes4j.bin.io.Cartridge; import cn.navclub.nes4j.bin.io.JoyPad; import cn.navclub.nes4j.bin.ppu.PPU; import lombok.Getter; -import lombok.extern.slf4j.Slf4j; import static cn.navclub.nes4j.bin.util.BinUtil.int8; import static cn.navclub.nes4j.bin.util.BinUtil.uint8; @@ -15,7 +12,6 @@ /** * @author GZYangKui */ -@Slf4j public class Bus implements Component { private static final int RPG_ROM = 0x8000; private static final int RPG_ROM_END = 0xFFFF; diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java b/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java index b815622..8ff5242 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/core/CPU.java @@ -3,6 +3,8 @@ import cn.navclub.nes4j.bin.NES; import cn.navclub.nes4j.bin.config.*; import cn.navclub.nes4j.bin.core.register.CPUStatus; +import cn.navclub.nes4j.bin.log.Logger; +import cn.navclub.nes4j.bin.log.LoggerAdapter; import lombok.Getter; import lombok.extern.slf4j.Slf4j; @@ -16,8 +18,9 @@ * * @author GZYangKui */ -@Slf4j public class CPU { + private final static Logger logger = LoggerAdapter.logger(CPU.class); + //Stack offset public static final int STACK = 0x0100; //Program counter reset offset @@ -375,12 +378,12 @@ public int next() { var mode = instruction6502.getAddressMode(); var instruction = instruction6502.getInstruction(); - if (log.isDebugEnabled()) { + if (logger.isDebugEnabled()) { var operand = ""; if (mode != AddressMode.Implied && mode != AddressMode.Accumulator && mode != AddressMode.Relative) { operand = "0x" + Integer.toHexString(this.modeProvider.getAbsAddr(mode)); } - log.debug( + logger.debug( "[0x{}] A:{} X:{} Y:{} S:{} {} {}", Integer.toHexString(this.pc - 1), Integer.toHexString(this.ra), diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/log/Level.java b/bin/src/main/java/cn/navclub/nes4j/bin/log/Level.java new file mode 100644 index 0000000..09e82ea --- /dev/null +++ b/bin/src/main/java/cn/navclub/nes4j/bin/log/Level.java @@ -0,0 +1,17 @@ +package cn.navclub.nes4j.bin.log; + +/** + * Enum all log level + * + * @author GZYangKui + */ +public enum Level { + ALL, + TRACE, + DEBUG, + INFO, + WARN, + ERROR, + FATAL, + OFF +} diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/log/Logger.java b/bin/src/main/java/cn/navclub/nes4j/bin/log/Logger.java new file mode 100644 index 0000000..99a9e2b --- /dev/null +++ b/bin/src/main/java/cn/navclub/nes4j/bin/log/Logger.java @@ -0,0 +1,42 @@ +package cn.navclub.nes4j.bin.log; + +public interface Logger { + /** + * Output a debug level message + * + * @param msg message content + * @param params message params + */ + void debug(String msg, Object... params); + + /** + * Output a info level message + * + * @param msg message content + * @param params message params + */ + void info(String msg, Object... params); + + /** + * Output a warning level message + * + * @param msg message content + * @param params message params + */ + void warning(String msg, Object... params); + + /** + * Output a fatal level message + * + * @param msg message content + * @param throwable exception detail + */ + void fatal(String msg, Throwable throwable); + + /** + * Whether debug is enable + * + * @return If debug is enable return {@code true} otherwise {@code false} + */ + boolean isDebugEnabled(); +} diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/log/LoggerAdapter.java b/bin/src/main/java/cn/navclub/nes4j/bin/log/LoggerAdapter.java new file mode 100644 index 0000000..d747a88 --- /dev/null +++ b/bin/src/main/java/cn/navclub/nes4j/bin/log/LoggerAdapter.java @@ -0,0 +1,20 @@ +package cn.navclub.nes4j.bin.log; + +import cn.navclub.nes4j.bin.log.impl.NLogger; + +public class LoggerAdapter { + private static final Level level; + + static { + var str = System.getProperty("nes4j.log.level"); + if (str == null || str.trim().equals("")) { + level = Level.INFO; + } else { + level = Level.valueOf(str.toUpperCase()); + } + } + + public static Logger logger(Class clazz) { + return new NLogger(clazz, level); + } +} diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/log/formatter/NFormatter.java b/bin/src/main/java/cn/navclub/nes4j/bin/log/formatter/NFormatter.java new file mode 100644 index 0000000..cffb0b3 --- /dev/null +++ b/bin/src/main/java/cn/navclub/nes4j/bin/log/formatter/NFormatter.java @@ -0,0 +1,72 @@ +package cn.navclub.nes4j.bin.log.formatter; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.Formatter; +import java.util.logging.Level; +import java.util.logging.LogRecord; +import java.util.regex.Pattern; + +public class NFormatter extends Formatter { + private final Pattern pattern; + private final SimpleDateFormat format; + + public NFormatter() { + this.pattern = Pattern.compile("\\{}"); + this.format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + } + + @Override + public String format(LogRecord record) { + var str = String.format("[%s [%s] [%-7s] [%s]", + this.format.format(new Date()), + Thread.currentThread().getName(), + record.getLevel().getName(), + record.getLoggerName() + ); + var message = record.getMessage(); + var params = record.getParameters(); + var length = params == null ? 0 : params.length; + + var index = 0; + var offset = 0; + var sb = new StringBuilder(message); + var matter = pattern.matcher(message); + while (matter.find() && index < length) { + var start = matter.start(); + var end = matter.end(); + var param = record.getParameters()[index]; + if (param == null) { + param = "nil"; + } + var value = param.toString(); + sb.replace(start + offset, end + offset, value); + offset += (value.length() - 2); + index++; + } + str = String.format("%s %s", str, sb); + + if (record.getLevel() == Level.SEVERE) { + var e = record.getThrown(); + if (e != null) { + str += "\n"; + str += throwable2Str(e); + } + } + str += "\n"; + return str; + } + + private String throwable2Str(Throwable throwable) { + try ( + var sw = new StringWriter(); + var pw = new PrintWriter(sw)) { + throwable.printStackTrace(pw); + return sw.toString(); + } catch (Exception e) { + return throwable2Str(new RuntimeException("Log exception parser error!")); + } + } +} diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/log/impl/NLogger.java b/bin/src/main/java/cn/navclub/nes4j/bin/log/impl/NLogger.java new file mode 100644 index 0000000..7e20178 --- /dev/null +++ b/bin/src/main/java/cn/navclub/nes4j/bin/log/impl/NLogger.java @@ -0,0 +1,55 @@ +package cn.navclub.nes4j.bin.log.impl; + +import cn.navclub.nes4j.bin.log.formatter.NFormatter; + +import java.util.logging.*; + +public class NLogger implements cn.navclub.nes4j.bin.log.Logger { + + private final Logger logger; + @SuppressWarnings("all") + private final Handler handler; + + public NLogger(Class clazz, cn.navclub.nes4j.bin.log.Level level) { + this.handler = new ConsoleHandler(); + this.handler.setFormatter(new NFormatter()); + this.logger = Logger.getLogger(clazz.getName()); + this.logger.addHandler(handler); + this.logger.setUseParentHandlers(false); + switch (level) { + case ALL -> this.logger.setLevel(Level.ALL); + case TRACE -> this.logger.setLevel(Level.FINEST); + case DEBUG -> this.logger.setLevel(Level.FINER); + case INFO -> this.logger.setLevel(Level.INFO); + case WARN -> this.logger.setLevel(Level.WARNING); + case FATAL -> this.logger.setLevel(Level.SEVERE); + case OFF -> this.logger.setLevel(Level.OFF); + } + } + + @Override + public void debug(String msg, Object... params) { + this.logger.log(Level.FINER, msg, params); + } + + @Override + public void info(String msg, Object... params) { + this.logger.log(Level.INFO, msg, params); + } + + @Override + public void warning(String msg, Object... params) { + this.logger.log(Level.WARNING, msg, params); + } + + @Override + public void fatal(String msg, Throwable throwable) { + this.logger.log(Level.SEVERE, msg, throwable); + } + + @Override + public boolean isDebugEnabled() { + var level = this.logger.getLevel(); + return level == Level.ALL || level.intValue() <= Level.CONFIG.intValue(); + } +} diff --git a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUControl.java b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUControl.java index 64afbe9..ebc09e0 100644 --- a/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUControl.java +++ b/bin/src/main/java/cn/navclub/nes4j/bin/ppu/register/PPUControl.java @@ -29,7 +29,7 @@ * * @author GZYangKui */ -@Slf4j + public class PPUControl extends Register { public PPUControl() { diff --git a/bin/src/main/java/module-info.java b/bin/src/main/java/module-info.java index 9a9243f..776c967 100644 --- a/bin/src/main/java/module-info.java +++ b/bin/src/main/java/module-info.java @@ -2,9 +2,10 @@ module cn.navclub.nes4j.bin { requires static lombok; - requires org.slf4j; + requires java.logging; exports cn.navclub.nes4j.bin; + exports cn.navclub.nes4j.bin.log; exports cn.navclub.nes4j.bin.core; exports cn.navclub.nes4j.bin.util; exports cn.navclub.nes4j.bin.ppu; @@ -17,6 +18,7 @@ exports cn.navclub.nes4j.bin.apu; exports cn.navclub.nes4j.bin.eventbus; exports cn.navclub.nes4j.bin.apu.impl.timer; + exports cn.navclub.nes4j.bin.log.impl; uses Player; } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9592250..2de3c6c 100644 --- a/pom.xml +++ b/pom.xml @@ -44,21 +44,6 @@ - - org.slf4j - slf4j-api - ${slf4j.version} - - - ch.qos.logback - logback-core - ${logback.version} - - - ch.qos.logback - logback-classic - ${logback.version} - com.fasterxml.jackson.core jackson-databind