All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.protostuff.compiler.cli.ProtostuffCompilerCli Maven / Gradle / Ivy

package io.protostuff.compiler.cli;

import com.google.common.collect.ImmutableMap;
import io.protostuff.compiler.model.ImmutableModuleConfiguration;
import io.protostuff.compiler.model.ModuleConfiguration;
import io.protostuff.compiler.parser.ParserException;
import io.protostuff.generator.CompilerModule;
import io.protostuff.generator.CompilerRegistry;
import io.protostuff.generator.GeneratorException;
import io.protostuff.generator.ProtostuffCompiler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.LoggerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Protostuff compiler command-line interface.
 *
 * @author Kostiantyn Shchepanovskyi
 */
public class ProtostuffCompilerCli extends ProtostuffCompiler {

    private static final String COMPILER_VERSION = ProtostuffCompilerCli.class.getPackage().getImplementationVersion();

    private static final String GENERATOR = "generator";
    private static final String TEMPLATE = "template";
    private static final String EXTENSIONS = "extensions";
    private static final String OUTPUT = "output";
    private static final String DEBUG = "debug";
    private static final String VERSION = "version";
    private static final String HELP = "help";
    private static final String PROTO_PATH = "proto_path";
    private static final ImmutableMap HELP_ITEMS_ORDER = ImmutableMap.builder()
            .put(HELP, 1)
            .put(PROTO_PATH, 2)
            .put(GENERATOR, 3)
            .put(OUTPUT, 4)
            .put(TEMPLATE, 5)
            .put(EXTENSIONS, 6)
            .put(DEBUG, 100)
            .build();
    private static final Logger LOGGER = LoggerFactory.getLogger(ProtostuffCompilerCli.class);

    public static void main(String[] args) {
        new ProtostuffCompilerCli().run(args);
    }

    private static void changeLogLevel(Level newLevel) {
        LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
        Configuration config = ctx.getConfiguration();
        LoggerConfig loggerConfig = config.getLoggerConfig(LogManager.ROOT_LOGGER_NAME);
        loggerConfig.setLevel(newLevel);
        ctx.updateLoggers();
    }

    private void run(String[] args) {
        CompilerRegistry registry = injector.getInstance(CompilerRegistry.class);
        Options options = new Options();
        options.addOption(Option.builder("h")
                .longOpt(HELP)
                .desc("Print this message.")
                .build());
        options.addOption(Option.builder("I")
                .longOpt(PROTO_PATH)
                .argName("dir")
                .numberOfArgs(1)
                .desc("Specify the directory in which to search for "
                        + "imports.  May be specified multiple times;"
                        + " directories will be searched in order.  If not"
                        + " given, the current working directory is used.")
                .build());
        options.addOption(Option.builder("d")
                .longOpt(DEBUG)
                .desc("Show debug information.")
                .build());
        options.addOption(Option.builder("v")
                .longOpt(VERSION)
                .desc("Show version.")
                .build());
        options.addOption(Option.builder("o")
                .longOpt(OUTPUT)
                .argName("dir")
                .numberOfArgs(1)
                .desc("Specify a directory for saving generated files.")
                .build());
        options.addOption(Option.builder("g")
                .longOpt(GENERATOR)
                .argName("name")
                .numberOfArgs(1)
                .desc("Specify compiler: " + String.join("|", registry.availableCompilers()))
                .build());
        options.addOption(Option.builder("t")
                .longOpt(TEMPLATE)
                .argName("file")
                .numberOfArgs(1)
                .desc("[st4] Specify a template for st4 compiler")
                .build());
        options.addOption(Option.builder("e")
                .longOpt(EXTENSIONS)
                .argName("class")
                .numberOfArgs(1)
                .desc("[st4] Specify full class name of an extensions provider for st4 compiler")
                .build());
        CommandLineParser parser = new DefaultParser();
        ImmutableModuleConfiguration.Builder builder = ImmutableModuleConfiguration.builder();
        builder.name("main");
        try {
            CommandLine cmd = parser.parse(options, args);
            if (cmd.hasOption(HELP)) {
                printHelp(options);
                return;
            }
            if (cmd.hasOption(VERSION)) {
                Package pkg = ProtostuffCompilerCli.class.getPackage();
                String version = pkg.getImplementationVersion();
                LOGGER.info("Version = {}", version);
                return;
            }
            if (cmd.hasOption(DEBUG)) {
                changeLogLevel(Level.DEBUG);
            }
            if (cmd.hasOption(GENERATOR)) {
                String generator = cmd.getOptionValue(GENERATOR);
                builder.generator(generator);
            } else {
                LOGGER.error("Generator is not set.");
                return;
            }
            if (cmd.hasOption(OUTPUT)) {
                String output = cmd.getOptionValue(OUTPUT);
                builder.output(output);
            } else {
                LOGGER.error("Output directory is not set.");
                return;
            }
            if (cmd.hasOption(TEMPLATE)) {
                List templates = Collections.singletonList(cmd.getOptionValue(TEMPLATE));
                builder.putOptions(CompilerModule.TEMPLATES_OPTION, templates);
            }
            if (cmd.hasOption(EXTENSIONS)) {
                builder.putOptions(CompilerModule.EXTENSIONS_OPTION, cmd.getOptionValue(EXTENSIONS));
            }
            List includePaths = new ArrayList<>();
            if (cmd.hasOption(PROTO_PATH)) {
                String[] paths = cmd.getOptionValues(PROTO_PATH);
                for (String path : paths) {
                    includePaths.add(Paths.get(path));
                }
            }
            if (includePaths.isEmpty()) {
                includePaths.add(Paths.get("."));
            }
            builder.includePaths(includePaths);
            List protoFiles = cmd.getArgList();
            builder.protoFiles(protoFiles);
        } catch (ParseException e) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.error("Could not parse command", e);
            } else {
                LOGGER.error(e.getMessage());
            }
            return;
        }

        LOGGER.info("Version={}", COMPILER_VERSION);

        ModuleConfiguration configuration = builder.build();

        if (configuration.getProtoFiles().isEmpty()) {
            LOGGER.error("Missing input file.");
            return;
        }
        if (configuration.getGenerator() == null) {
            LOGGER.error("Missing generator directives.");
            return;
        }
        try {
            compile(configuration);
        } catch (GeneratorException | ParserException e) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.error("Compilation error", e);
            } else {
                LOGGER.error(e.getMessage());
            }
        }
    }

    private void printHelp(Options options) {
        // automatically generate the help statement
        HelpFormatter formatter = new HelpFormatter();
        formatter.setWidth(79);
        formatter.setOptionComparator(Comparator.comparingInt(this::getOptionOrder));
        formatter.printHelp("protostuff-compiler [options] proto_files", options);
    }

    private Integer getOptionOrder(Option o) {
        return HELP_ITEMS_ORDER.getOrDefault(o.getLongOpt(), 99);
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy