added Wcfg file parser and CLI

This commit is contained in:
2023-10-30 22:30:00 +08:00
parent b7d00d9d9c
commit 9cb37790c2
45 changed files with 1445 additions and 219 deletions

View File

@@ -1,21 +1,68 @@
plugins {
id 'maven-publish'
alias catalog.plugins.envelope
alias catalog.plugins.kotlin.jvm
alias catalog.plugins.graalvm.native.image
alias catalog.plugins.sambal
}
import net.woggioni.gradle.graalvm.NativeImageTask
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
dependencies {
implementation catalog.kotlin.stdlib.jdk8
implementation catalog.jcommander
implementation catalog.jwo
implementation catalog.picocli
implementation catalog.slf4j.simple
implementation rootProject
implementation project(':wcfg')
}
envelopeJar {
mainClass = 'net.woggioni.wson.cli.MainKt'
application {
mainClass = 'net.woggioni.wson.cli.WsonCli'
mainModule = 'net.woggioni.wson.cli'
}
compileJava {
options.compilerArgs = [
"--patch-module",
"net.woggioni.wson.cli=${sourceSets.main.output.asPath}"
]
options.javaModuleMainClass = 'net.woggioni.wson.cli.MainKt'
options.javaModuleVersion = project.version
}
configureNativeImage {
// args = [
// 'wson',
// '-f',
// '../test-utils/src/main/resources/wordpress.json',
// '-t',
// 'jbon',
// '-o',
// '/dev/null'
// ]
args = [
'wcfg',
'-f',
'../wcfg/src/test/resources/build.wcfg',
'-t',
'jbon',
'-o',
'/dev/null'
]
mergeConfiguration = true
}
Provider<NativeImageTask> nativeImageTaskProvider = tasks.named("nativeImage") {
useMusl = true
buildStaticImage = true
}
artifacts {
archives nativeImageTaskProvider.map(NativeImageTask.&getOutputFile)
}
publishing {
repositories {
maven {
@@ -25,7 +72,11 @@ publishing {
publications {
myDistribution(MavenPublication) {
artifact envelopeJar
def host = DefaultNativePlatform.host()
artifact(
source: nativeImageTaskProvider,
classifier: host.operatingSystem.name + '-' + host.architecture.name
)
}
}
}

View File

@@ -0,0 +1,6 @@
[
{
"name":"java.lang.Boolean",
"methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }]
}
]

View File

@@ -0,0 +1 @@
Args=-H:Optimize=3 --initialize-at-run-time=net.woggioni.wson.cli.WsonCli

View File

@@ -0,0 +1,8 @@
[
{
"type":"agent-extracted",
"classes":[
]
}
]

View File

@@ -0,0 +1,2 @@
[
]

View File

@@ -0,0 +1,248 @@
[
{
"name":"com.sun.crypto.provider.AESCipher$General",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.ARCFOURCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.ChaCha20Cipher$ChaCha20Poly1305",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.DESCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.DESedeCipher",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"com.sun.crypto.provider.GaloisCounterMode$AESGCM",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"groovy.lang.Closure"
},
{
"name":"java.lang.Object",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true
},
{
"name":"java.nio.file.Path"
},
{
"name":"java.nio.file.Paths",
"methods":[{"name":"get","parameterTypes":["java.lang.String","java.lang.String[]"] }]
},
{
"name":"java.security.AlgorithmParametersSpi"
},
{
"name":"java.security.KeyStoreSpi"
},
{
"name":"java.security.SecureRandomParameters"
},
{
"name":"java.sql.Connection"
},
{
"name":"java.sql.Driver"
},
{
"name":"java.sql.DriverManager",
"methods":[{"name":"getConnection","parameterTypes":["java.lang.String"] }, {"name":"getDriver","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.sql.Time",
"methods":[{"name":"<init>","parameterTypes":["long"] }]
},
{
"name":"java.sql.Timestamp",
"methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.time.Duration",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.Instant",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.LocalDate",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.LocalDateTime",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.LocalTime",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.MonthDay",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.OffsetDateTime",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.OffsetTime",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.Period",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.Year",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.YearMonth",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"java.time.ZoneId",
"methods":[{"name":"of","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.time.ZoneOffset",
"methods":[{"name":"of","parameterTypes":["java.lang.String"] }]
},
{
"name":"java.time.ZonedDateTime",
"methods":[{"name":"parse","parameterTypes":["java.lang.CharSequence"] }]
},
{
"name":"javax.security.auth.x500.X500Principal",
"fields":[{"name":"thisX500Name"}],
"methods":[{"name":"<init>","parameterTypes":["sun.security.x509.X500Name"] }]
},
{
"name":"net.woggioni.wson.cli.OutputTypeConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"net.woggioni.wson.cli.SerializationTypeConverter",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"net.woggioni.wson.cli.VersionProvider",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"net.woggioni.wson.cli.WcfgCommand",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"net.woggioni.wson.cli.WsonCli",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true
},
{
"name":"net.woggioni.wson.cli.WsonCommand",
"allDeclaredFields":true,
"queryAllDeclaredMethods":true,
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.pkcs12.PKCS12KeyStore",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.pkcs12.PKCS12KeyStore$DualFormatPKCS12",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.JavaKeyStore$JKS",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.NativePRNG",
"methods":[{"name":"<init>","parameterTypes":[] }, {"name":"<init>","parameterTypes":["java.security.SecureRandomParameters"] }]
},
{
"name":"sun.security.provider.SHA",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.provider.X509Factory",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.rsa.RSAKeyFactory$Legacy",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.KeyManagerFactoryImpl$SunX509",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.SSLContextImpl$DefaultSSLContext",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.ssl.TrustManagerFactoryImpl$PKIXFactory",
"methods":[{"name":"<init>","parameterTypes":[] }]
},
{
"name":"sun.security.x509.AuthorityInfoAccessExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.AuthorityKeyIdentifierExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.BasicConstraintsExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.CRLDistributionPointsExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.CertificatePoliciesExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.ExtendedKeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.IssuerAlternativeNameExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.KeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.NetscapeCertTypeExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.PrivateKeyUsageExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.SubjectAlternativeNameExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
},
{
"name":"sun.security.x509.SubjectKeyIdentifierExtension",
"methods":[{"name":"<init>","parameterTypes":["java.lang.Boolean","java.lang.Object"] }]
}
]

View File

@@ -0,0 +1,17 @@
{
"resources":{
"includes":[{
"pattern":"\\QMETA-INF/MANIFEST.MF\\E"
}, {
"pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E"
}, {
"pattern":"\\QMETA-INF/services/java.net.spi.URLStreamHandlerProvider\\E"
}, {
"pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E"
}, {
"pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E"
}, {
"pattern":"\\Qsimplelogger.properties\\E"
}]},
"bundles":[]
}

View File

@@ -0,0 +1,8 @@
{
"types":[
],
"lambdaCapturingTypes":[
],
"proxies":[
]
}

View File

@@ -1,8 +0,0 @@
module net.woggioni.wson.cli {
requires kotlin.stdlib;
requires kotlin.stdlib.jdk8;
requires net.woggioni.wson;
requires com.beust.jcommander;
opens net.woggioni.wson.cli to com.beust.jcommander;
}

View File

@@ -1,4 +0,0 @@
package net.woggioni.wson.cli;
public class Foo {
}

View File

@@ -0,0 +1,12 @@
module net.woggioni.wson.cli {
requires static lombok;
requires net.woggioni.jwo;
requires net.woggioni.wson;
requires net.woggioni.wson.wcfg;
requires org.slf4j;
requires org.slf4j.simple;
requires info.picocli;
exports net.woggioni.wson.cli;
opens net.woggioni.wson.cli to info.picocli;
}

View File

@@ -0,0 +1,51 @@
package net.woggioni.wson.cli;
import lombok.SneakyThrows;
import picocli.CommandLine;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.Objects;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
abstract class AbstractVersionProvider implements CommandLine.IVersionProvider {
private String version;
private String vcsHash;
@SneakyThrows
protected AbstractVersionProvider(String specificationTitle) {
String version = null;
String vcsHash = null;
Enumeration<URL> it = getClass().getClassLoader().getResources(JarFile.MANIFEST_NAME);
while (it.hasMoreElements()) {
URL manifestURL = it.nextElement();
Manifest mf = new Manifest();
try (InputStream inputStream = manifestURL.openStream()) {
mf.read(inputStream);
}
Attributes mainAttributes = mf.getMainAttributes();
if (Objects.equals(specificationTitle, mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE))) {
version = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION);
vcsHash = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
}
}
if (version == null || vcsHash == null) {
throw new RuntimeException("Version information not found in manifest");
}
this.version = version;
this.vcsHash = vcsHash;
}
@Override
public String[] getVersion() {
if (version.endsWith("-SNAPSHOT")) {
return new String[]{version, vcsHash};
} else {
return new String[]{version};
}
}
}

View File

@@ -0,0 +1,34 @@
package net.woggioni.wson.cli;
import lombok.RequiredArgsConstructor;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.woggioni.jwo.JWO.newThrowable;
@RequiredArgsConstructor
enum SerializationFormat {
JSON("json"), JBON("jbon");
private final String name;
public static SerializationFormat parse(String value) {
return Arrays.stream(SerializationFormat.values())
.filter(sf -> Objects.equals(sf.name, value))
.findFirst()
.orElseThrow(() -> {
var availableValues = Stream.of(
JSON,
JBON
).map(SerializationFormat::name).collect(Collectors.joining(", "));
throw newThrowable(IllegalArgumentException.class,
"Unknown serialization format '%s', possible values are %s",
value, availableValues
);
});
}
}

View File

@@ -0,0 +1,10 @@
package net.woggioni.wson.cli;
import picocli.CommandLine;
class SerializationTypeConverter implements CommandLine.ITypeConverter<SerializationFormat> {
@Override
public SerializationFormat convert(String value) {
return SerializationFormat.parse(value);
}
}

View File

@@ -0,0 +1,7 @@
package net.woggioni.wson.cli;
class VersionProvider extends AbstractVersionProvider {
protected VersionProvider() {
super("wson-cli");
}
}

View File

@@ -0,0 +1,92 @@
package net.woggioni.wson.cli;
import lombok.NoArgsConstructor;
import lombok.SneakyThrows;
import net.woggioni.jwo.Fun;
import net.woggioni.wson.serialization.binary.JBONDumper;
import net.woggioni.wson.serialization.json.JSONDumper;
import net.woggioni.wson.value.ObjectValue;
import net.woggioni.wson.wcfg.WConfig;
import net.woggioni.wson.xface.Value;
import picocli.CommandLine;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
@CommandLine.Command(
name = "wcfg",
versionProvider = VersionProvider.class)
public class WcfgCommand implements Runnable {
@CommandLine.Option(
names = {"-f", "--file"},
description = {"Name of the input file to parse"}
)
private Path fileName;
@CommandLine.Option(names = {"-o", "--output"},
description = {"Name of the JSON file to generate"})
private Path output;
@CommandLine.Option(
names = {"-t", "--type"},
description = {"Output type"},
converter = {SerializationTypeConverter.class})
private SerializationFormat outputType = SerializationFormat.JSON;
@CommandLine.Option(names = {"-d", "--resolve-refernces"}, description = "Resolve references")
private boolean resolveReferences = false;
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true)
private boolean help = false;
@SneakyThrows
public void run() {
Value.Configuration cfg = Value.Configuration.builder()
.objectValueImplementation(ObjectValue.Implementation.LinkedHashMap)
.serializeReferences(!resolveReferences)
.build();
InputStream inputStream;
if (fileName != null) {
inputStream = new BufferedInputStream(Files.newInputStream(fileName));
} else {
inputStream = System.in;
}
Value result;
try(Reader reader = new InputStreamReader(inputStream)) {
WConfig wcfg = WConfig.parse(reader, cfg);
result = wcfg.whole();
}
OutputStream outputStream = Optional.ofNullable(output)
.map((Fun<Path, OutputStream>) Files::newOutputStream)
.<OutputStream>map(BufferedOutputStream::new)
.orElse(System.out);
switch (outputType) {
case JSON:
try (Writer writer = new OutputStreamWriter(outputStream)) {
new JSONDumper(cfg).dump(result, writer);
}
break;
case JBON:
try {
new JBONDumper(cfg).dump(result, outputStream);
} finally {
outputStream.close();
}
}
}
}

View File

@@ -0,0 +1,33 @@
package net.woggioni.wson.cli;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import picocli.CommandLine;
@Slf4j
@CommandLine.Command(
name = "wcfg",
versionProvider = VersionProvider.class,
subcommands = {WsonCommand.class, WcfgCommand.class})
public class WsonCli implements Runnable {
public static void main(String[] args) {
final var commandLine = new CommandLine(new WsonCli());
commandLine.setExecutionExceptionHandler((ex, cl, parseResult) -> {
log.error(ex.getMessage(), ex);
return CommandLine.ExitCode.SOFTWARE;
});
System.exit(commandLine.execute(args));
}
@Getter
@CommandLine.Option(names = {"-V", "--version"}, versionHelp = true)
private boolean versionHelp;
@CommandLine.Spec
private CommandLine.Model.CommandSpec spec;
@Override
public void run() {
spec.commandLine().usage(System.out);
}
}

View File

@@ -0,0 +1,104 @@
package net.woggioni.wson.cli;
import lombok.SneakyThrows;
import net.woggioni.jwo.Fun;
import net.woggioni.wson.serialization.binary.JBONDumper;
import net.woggioni.wson.serialization.binary.JBONParser;
import net.woggioni.wson.serialization.json.JSONDumper;
import net.woggioni.wson.serialization.json.JSONParser;
import net.woggioni.wson.xface.Value;
import picocli.CommandLine;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Optional;
import static net.woggioni.jwo.JWO.newThrowable;
@CommandLine.Command(
name = "wson",
versionProvider = VersionProvider.class)
public class WsonCommand implements Runnable {
@CommandLine.Option(
names = {"-f", "--file"},
description = {"Name of the input file to parse"}
)
private Path fileName;
@CommandLine.Option(
names = {"--input-type"},
description = {"Input type"},
converter = {SerializationTypeConverter.class})
private SerializationFormat inputType = SerializationFormat.JSON;
@CommandLine.Option(names = {"-o", "--output"},
description = {"Name of the JSON file to generate"})
private Path output;
@CommandLine.Option(
names = {"-t", "--type"},
description = {"Output type"},
converter = {SerializationTypeConverter.class})
private SerializationFormat outputType = SerializationFormat.JSON;
@CommandLine.Option(names = {"-h", "--help"}, usageHelp = true)
private boolean help = false;
@SneakyThrows
public void run() {
Value.Configuration cfg = Value.Configuration.builder().serializeReferences(true).build();
InputStream inputStream;
if (fileName != null) {
inputStream = new BufferedInputStream(Files.newInputStream(fileName));
} else {
inputStream = System.in;
}
Value result;
switch (inputType) {
case JSON:
try (Reader reader = new InputStreamReader(inputStream)) {
result = new JSONParser(cfg).parse(reader);
}
break;
case JBON:
try {
result = new JBONParser(cfg).parse(inputStream);
} finally {
inputStream.close();
}
break;
default:
throw newThrowable(RuntimeException.class, "This sohuld never happen");
}
OutputStream outputStream = Optional.ofNullable(output)
.map((Fun<Path, OutputStream>) Files::newOutputStream)
.<OutputStream>map(BufferedOutputStream::new)
.orElse(System.out);
switch (outputType) {
case JSON:
try (Writer writer = new OutputStreamWriter(outputStream)) {
new JSONDumper(cfg).dump(result, writer);
}
break;
case JBON:
try {
new JBONDumper(cfg).dump(result, outputStream);
} finally {
outputStream.close();
}
}
}
}

View File

@@ -1,9 +0,0 @@
module net.woggioni.wson.cli {
requires kotlin.stdlib;
requires kotlin.stdlib.jdk8;
requires net.woggioni.wson;
requires com.beust.jcommander;
exports net.woggioni.wson.cli;
opens net.woggioni.wson.cli to com.beust.jcommander;
}

View File

@@ -0,0 +1,45 @@
package net.woggioni.wson.cli
import java.net.URL
import java.util.Enumeration
import java.util.jar.Attributes
import java.util.jar.JarFile
import java.util.jar.Manifest
import lombok.SneakyThrows
import picocli.CommandLine
abstract class AbstractVersionProvider @SneakyThrows protected constructor(specificationTitle: String?) :
CommandLine.IVersionProvider {
private val version: String
private val vcsHash: String
init {
var version: String? = null
var vcsHash: String? = null
val it: Enumeration<URL> = javaClass.classLoader.getResources(JarFile.MANIFEST_NAME)
while (it.hasMoreElements()) {
val manifestURL: URL = it.nextElement()
val mf = Manifest()
manifestURL.openStream().use(mf::read)
val mainAttributes: Attributes = mf.mainAttributes
if (specificationTitle == mainAttributes.getValue(Attributes.Name.SPECIFICATION_TITLE)) {
version = mainAttributes.getValue(Attributes.Name.SPECIFICATION_VERSION)
vcsHash = mainAttributes.getValue(Attributes.Name.IMPLEMENTATION_VERSION)
}
}
if (version == null || vcsHash == null) {
throw RuntimeException("Version information not found in manifest")
}
this.version = version
this.vcsHash = vcsHash
}
override fun getVersion(): Array<String?> {
return if (version.endsWith("-SNAPSHOT")) {
arrayOf(version, vcsHash)
} else {
arrayOf(version)
}
}
}

View File

@@ -7,16 +7,13 @@ import java.io.OutputStreamWriter
import java.nio.file.Files
import java.nio.file.Path
import kotlin.system.exitProcess
import com.beust.jcommander.IStringConverter
import com.beust.jcommander.JCommander
import com.beust.jcommander.Parameter
import com.beust.jcommander.ParameterException
import com.beust.jcommander.converters.PathConverter
import net.woggioni.wson.serialization.binary.JBONDumper
import net.woggioni.wson.serialization.binary.JBONParser
import net.woggioni.wson.serialization.json.JSONDumper
import net.woggioni.wson.serialization.json.JSONParser
import net.woggioni.wson.xface.Value
import org.slf4j.LoggerFactory
import picocli.CommandLine
sealed class SerializationFormat(val name: String) {
@@ -41,88 +38,99 @@ sealed class SerializationFormat(val name: String) {
}
}
private class OutputTypeConverter : IStringConverter<SerializationFormat> {
class OutputTypeConverter : CommandLine.ITypeConverter<SerializationFormat> {
override fun convert(value: String): SerializationFormat = SerializationFormat.parse(value)
}
private class CliArg {
@Parameter(names = ["-f", "--file"], description = "Name of the input file to parse", converter = PathConverter::class)
class VersionProvider internal constructor() : AbstractVersionProvider("wson-cli")
@CommandLine.Command(
name = "wson-cli",
versionProvider = VersionProvider::class)
private class WsonCli : Runnable {
@CommandLine.Option(
names = ["-f", "--file"],
description = ["Name of the input file to parse"],
)
var fileName: Path? = null
@Parameter(names = ["--input-type"], description = "Input type", converter = OutputTypeConverter::class)
@CommandLine.Option(
names = ["--input-type"],
description = ["Input type"],
converter = [OutputTypeConverter::class])
var inputType: SerializationFormat = SerializationFormat.JSON
@Parameter(names = ["-o", "--output"], description = "Name of the JSON file to generate", converter = PathConverter::class)
@CommandLine.Option(names = ["-o", "--output"],
description = ["Name of the JSON file to generate"])
var output: Path? = null
@Parameter(names = ["-t", "--type"], description = "Output type", converter = OutputTypeConverter::class)
@CommandLine.Option(
names = ["-t", "--type"],
description = ["Output type"],
converter = [OutputTypeConverter::class])
var outputType: SerializationFormat = SerializationFormat.JSON
@Parameter(names = ["-h", "--help"], help = true)
@CommandLine.Option(names = ["-h", "--help"], usageHelp = true)
var help: Boolean = false
override fun run() {
val cfg = Value.Configuration.builder().serializeReferences(true).build()
val inputStream = if (fileName != null) {
BufferedInputStream(Files.newInputStream(fileName))
} else {
System.`in`
}
val result = when(inputType) {
SerializationFormat.JSON -> {
val reader = InputStreamReader(inputStream)
try {
JSONParser(cfg).parse(reader)
} finally {
reader.close()
}
}
SerializationFormat.JBON -> {
try {
JBONParser(cfg).parse(inputStream)
} finally {
inputStream.close()
}
}
}
val outputStream = output?.let {
BufferedOutputStream(Files.newOutputStream(it))
} ?: System.out
when(outputType) {
SerializationFormat.JSON -> {
val writer = OutputStreamWriter(outputStream)
try {
JSONDumper(cfg).dump(result, writer)
} finally {
writer.close()
}
}
SerializationFormat.JBON -> {
try {
JBONDumper(cfg).dump(result, outputStream)
} finally {
outputStream.close()
}
}
}
}
}
fun main(vararg args: String) {
val cliArg = CliArg()
val cliArgumentParser = JCommander.newBuilder()
.addObject(cliArg)
.build()
try {
cliArgumentParser.parse(*args)
} catch (pe: ParameterException) {
cliArgumentParser.usage()
exitProcess(-1)
}
if (cliArg.help) {
cliArgumentParser.usage()
exitProcess(0)
}
val cfg = Value.Configuration.builder().serializeReferences(true).build()
val inputStream = if (cliArg.fileName != null) {
BufferedInputStream(Files.newInputStream(cliArg.fileName))
} else {
System.`in`
}
val result = when(cliArg.inputType) {
SerializationFormat.JSON -> {
val reader = InputStreamReader(inputStream)
try {
JSONParser(cfg).parse(reader)
} finally {
reader.close()
}
}
SerializationFormat.JBON -> {
try {
JBONParser(cfg).parse(inputStream)
} finally {
inputStream.close()
}
}
}
val outputStream = if (cliArg.output != null) {
BufferedOutputStream(Files.newOutputStream(cliArg.output))
} else {
System.out
}
when(cliArg.outputType) {
SerializationFormat.JSON -> {
val writer = OutputStreamWriter(outputStream)
try {
JSONDumper(cfg).dump(result, writer)
} finally {
writer.close()
}
}
SerializationFormat.JBON -> {
try {
JBONDumper(cfg).dump(result, outputStream)
} finally {
outputStream.close()
}
}
val log = LoggerFactory.getLogger("wson-cli")
val commandLine = CommandLine(WsonCli())
commandLine.setExecutionExceptionHandler { ex, cl, parseResult ->
log.error(ex.message, ex)
CommandLine.ExitCode.SOFTWARE
}
exitProcess(commandLine.execute(*args))
}