From 014359d6145155236912d252d4fe4e7cb0531cb4 Mon Sep 17 00:00:00 2001 From: MeryKitty Date: Mon, 12 Apr 2021 23:23:44 +0700 Subject: [PATCH] Use logger --- .gitignore | 2 +- .../io/github/merykitty/meryslp/Info.java | 7 ++++- .../github/merykitty/meryslp/SLPDecoder.java | 16 ++++++----- .../github/merykitty/meryslp/SLPEncoder.java | 16 ++++++----- .../io/github/merykitty/meryslp/Test.java | 2 ++ .../meryslp/misc/EnvironmentResolver.java | 25 ++++++++++++++++++ src/main/java/module-info.java | 1 + src/main/resources/unix-x64/icon.png | Bin 0 -> 4260 bytes .../resources/windows-x64/decoder.properties | 2 +- .../resources/windows-x64/encoder.properties | 4 +-- src/main/resources/windows-x64/icon.ico | Bin 0 -> 25214 bytes 11 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 src/main/resources/unix-x64/icon.png create mode 100644 src/main/resources/windows-x64/icon.ico diff --git a/.gitignore b/.gitignore index 1a5cb52..0909ed1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ /target/ /resources/ /data/ -/SLPProcessor/ +/MerySLP/ /slp-processor.iml /.idea/ *.jfr diff --git a/src/main/java/io/github/merykitty/meryslp/Info.java b/src/main/java/io/github/merykitty/meryslp/Info.java index 3712c62..96fc516 100644 --- a/src/main/java/io/github/merykitty/meryslp/Info.java +++ b/src/main/java/io/github/merykitty/meryslp/Info.java @@ -1,7 +1,12 @@ package io.github.merykitty.meryslp; +import io.github.merykitty.meryslp.misc.EnvironmentResolver; + public class Info { public static void main(String[] args) { - + EnvironmentResolver.info( + """ + """ + ); } } diff --git a/src/main/java/io/github/merykitty/meryslp/SLPDecoder.java b/src/main/java/io/github/merykitty/meryslp/SLPDecoder.java index 169ef8f..07b5b2f 100644 --- a/src/main/java/io/github/merykitty/meryslp/SLPDecoder.java +++ b/src/main/java/io/github/merykitty/meryslp/SLPDecoder.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.logging.Level; import io.github.merykitty.meryslp.misc.EnvironmentResolver; import io.github.merykitty.meryslp.misc.PrimitiveOptional; @@ -20,6 +21,8 @@ public class SLPDecoder { private static final Path DEFAULT_OUTPUT_FOLDER = Path.of("data/decoder-output"); public static void main(String[] args) throws IOException { + EnvironmentResolver.setLogLevel(Level.INFO); + var parser = ArgumentParsers.newFor("SLPDecoder").build() .defaultHelp(true) .description("Decode SLP files into human readable graphics images and meta data"); @@ -33,7 +36,6 @@ public static void main(String[] args) throws IOException { try { ns = parser.parseArgs(args); } catch (ArgumentParserException e) { - System.out.println("Incorrect command line format"); return; } var configFile = EnvironmentResolver.homeDir().resolve(DEFAULT_CONFIG_FILE); @@ -55,25 +57,25 @@ public static void main(String[] args) throws IOException { processSLPFile(path, outputFolder, palettes); }); } catch (RuntimeException e) { - System.out.println("Error: " + e.getCause().toString()); + EnvironmentResolver.error("Error: " + e.getCause().toString()); } catch (Exception e) { - System.out.println("Error: " + e.toString()); + EnvironmentResolver.error("Error: " + e.toString()); } } private static void processSLPFile(Path inputFile, Path outputFolder, PaletteContainer palettes) { try { var fileName = inputFile.getFileName(); - System.out.println("File name: " + fileName.toString()); + EnvironmentResolver.info("File name: " + fileName.toString()); long start = System.currentTimeMillis(); var file = SLPFiles.decode(inputFile, palettes); long mid = System.currentTimeMillis(); - System.out.println("Read slp file: " + (mid - start) + " ms"); + EnvironmentResolver.info("Read slp file: " + (mid - start) + " ms"); file.exportGraphics(outputFolder.resolve(fileName)); long end = System.currentTimeMillis(); - System.out.println("Print data: " + (end - mid) + " ms"); + EnvironmentResolver.info("Print data: " + (end - mid) + " ms"); } catch (Exception e) { - System.out.println(e); + EnvironmentResolver.info(e); } } } diff --git a/src/main/java/io/github/merykitty/meryslp/SLPEncoder.java b/src/main/java/io/github/merykitty/meryslp/SLPEncoder.java index affb339..50c9e32 100644 --- a/src/main/java/io/github/merykitty/meryslp/SLPEncoder.java +++ b/src/main/java/io/github/merykitty/meryslp/SLPEncoder.java @@ -11,6 +11,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.logging.Level; public class SLPEncoder { private static final Path DEFAULT_CONFIG_FILE = Path.of("resources/aoe1-config.json"); @@ -19,6 +20,8 @@ public class SLPEncoder { private static final Path DEFAULT_OUTPUT_FOLDER = Path.of("data/encoder-output"); public static void main(String[] args) throws IOException { + EnvironmentResolver.setLogLevel(Level.INFO); + var parser = ArgumentParsers.newFor("SLPDecoder").build() .defaultHelp(true) .description("Encode human readable graphics images and meta data to SLP files"); @@ -32,7 +35,6 @@ public static void main(String[] args) throws IOException { try { ns = parser.parseArgs(args); } catch (ArgumentParserException e) { - System.out.println("Incorrect command line format"); return; } @@ -53,25 +55,25 @@ public static void main(String[] args) throws IOException { files.filter(Files::isDirectory) .forEach(path -> encodeSLP(path, outputFolder, palettes)); } catch (RuntimeException e) { - System.out.println("Error: " + e.getCause().toString()); + EnvironmentResolver.error("Error: " + e.getCause().toString()); } catch (Exception e) { - System.out.println("Error: " + e.toString()); + EnvironmentResolver.error("Error: " + e.toString()); } } private static void encodeSLP(Path inputFile, Path outputFolder, PaletteContainer palettes) { try { var fileName = inputFile.getFileName(); - System.out.println("File name: " + fileName.toString()); + EnvironmentResolver.info("File name: " + fileName.toString()); long start = System.currentTimeMillis(); var file = SLPFiles.importGraphics(inputFile, palettes); long mid = System.currentTimeMillis(); - System.out.println("Import graphics: " + (mid - start) + " ms"); + EnvironmentResolver.info("Import graphics: " + (mid - start) + " ms"); SLPFiles.encode(outputFolder.resolve(fileName), palettes, file, true); long end = System.currentTimeMillis(); - System.out.println("Encode slp file: " + (end - mid) + " ms"); + EnvironmentResolver.info("Encode slp file: " + (end - mid) + " ms"); } catch (Exception e) { - System.out.println(e.toString()); + EnvironmentResolver.info(e); } } } diff --git a/src/main/java/io/github/merykitty/meryslp/Test.java b/src/main/java/io/github/merykitty/meryslp/Test.java index a5b8d83..59e5c3d 100644 --- a/src/main/java/io/github/merykitty/meryslp/Test.java +++ b/src/main/java/io/github/merykitty/meryslp/Test.java @@ -3,6 +3,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.logging.Level; import io.github.merykitty.meryslp.common.SLPFiles; import io.github.merykitty.meryslp.image.PaletteContainer; @@ -18,6 +19,7 @@ public class Test { private static final Path ENCODE_OUTPUT_FOLDER = HOME_DIR.resolve("data/encoder-output"); public static void main(String[] args) throws IOException { + EnvironmentResolver.setLogLevel(Level.ALL); // var palettes = new PaletteContainer(CONFIG_FILE, PALETTE_FOLDER); // var files = Files.list(DECODE_INPUT_FOLDER); // files.filter(Files::isRegularFile) diff --git a/src/main/java/io/github/merykitty/meryslp/misc/EnvironmentResolver.java b/src/main/java/io/github/merykitty/meryslp/misc/EnvironmentResolver.java index c9cf7de..0251127 100644 --- a/src/main/java/io/github/merykitty/meryslp/misc/EnvironmentResolver.java +++ b/src/main/java/io/github/merykitty/meryslp/misc/EnvironmentResolver.java @@ -6,6 +6,9 @@ import java.lang.invoke.MethodType; import java.nio.file.Files; import java.nio.file.Path; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; public class EnvironmentResolver { private static final long INIT_MAX_PATH_LENGTH = 256; @@ -13,10 +16,12 @@ public class EnvironmentResolver { private static final String OS_NAME; private static final Path HOME_DIR; + private static final Logger LOGGER = Logger.getGlobal(); static { try { OS_NAME = System.getProperty("os.name").toLowerCase(); + LOGGER.addHandler(new ConsoleHandler()); if (OS_NAME.contains("linux")) { var execPath = Files.readSymbolicLink(Path.of("/proc/self/exe")); var execName = execPath.getFileName().toString(); @@ -83,6 +88,10 @@ public class EnvironmentResolver { } } + public static void setLogLevel(Level level) { + LOGGER.setLevel(level); + } + public static Path homeDir() { return HOME_DIR; } @@ -90,4 +99,20 @@ public static Path homeDir() { public static String osName() { return OS_NAME; } + + public static void debug(Object message) { + LOGGER.fine(message.toString()); + } + + public static void info(Object message) { + LOGGER.info(message.toString()); + } + + public static void warning(Object message) { + LOGGER.warning(message.toString()); + } + + public static void error(Object message) { + LOGGER.severe(message.toString()); + } } diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 9b4d9a1..5dc87c4 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -1,4 +1,5 @@ module io.github.merykitty.meryslp { + requires java.logging; requires jdk.unsupported; requires jdk.incubator.foreign; requires org.json; diff --git a/src/main/resources/unix-x64/icon.png b/src/main/resources/unix-x64/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..dcd44b45cb6d589187e8a4e28beb423772f6eee5 GIT binary patch literal 4260 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/windows-x64/decoder.properties b/src/main/resources/windows-x64/decoder.properties index eee38ba..a1db3cf 100644 --- a/src/main/resources/windows-x64/decoder.properties +++ b/src/main/resources/windows-x64/decoder.properties @@ -1,4 +1,4 @@ java-options=-Dforeign.restricted=permit -XX:+UseParallelGC -XX:+UnlockExperimentalVMOptions -XX:+TrustFinalNonStaticFields module=io.github.merykitty.meryslp/io.github.merykitty.meryslp.SLPDecoder -icon=./resources/icon.png +icon=./resources/icon.ico win-console=true diff --git a/src/main/resources/windows-x64/encoder.properties b/src/main/resources/windows-x64/encoder.properties index 18ac02f..db2fa06 100644 --- a/src/main/resources/windows-x64/encoder.properties +++ b/src/main/resources/windows-x64/encoder.properties @@ -1,4 +1,4 @@ java-options=-Dforeign.restricted=permit -XX:+UseParallelGC -XX:+UnlockExperimentalVMOptions -XX:+TrustFinalNonStaticFields -module=io.github.merykitty.slpprocessor/io.github.merykitty.slpprocessor.SLPEncoder -icon=./resources/icon.png +module=io.github.merykitty.meryslp/io.github.merykitty.meryslp.SLPEncoder +icon=./resources/icon.ico win-console=true diff --git a/src/main/resources/windows-x64/icon.ico b/src/main/resources/windows-x64/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8d2c9571ed9e536a5fc46e043731b65759b928f8 GIT binary patch literal 25214 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 z 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