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

com.github.fge.jsonschema.main.cli.Main Maven / Gradle / Ivy

There is a newer version: 2.2.14
Show newest version
/*
 * Copyright (c) 2014, Francis Galiegue ([email protected])
 *
 * This software is dual-licensed under:
 *
 * - the Lesser General Public License (LGPL) version 3.0 or, at your option, any
 *   later version;
 * - the Apache Software License (ASL) version 2.0.
 *
 * The text of this file and of both licenses is available at the root of this
 * project or, if you have the jar distribution, in directory META-INF/, under
 * the names LGPL-3.0.txt and ASL-2.0.txt respectively.
 *
 * Direct link to the sources:
 *
 * - LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
 * - ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
 */

package com.github.fge.jsonschema.main.cli;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.fge.jackson.JacksonUtils;
import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.github.fge.jsonschema.core.load.configuration.LoadingConfiguration;
import com.github.fge.jsonschema.core.load.uri.URITranslatorConfiguration;
import com.github.fge.jsonschema.core.load.uri.URITranslatorConfigurationBuilder;
import com.github.fge.jsonschema.core.util.URIUtils;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.processors.syntax.SyntaxValidator;
import com.google.common.collect.Lists;
import joptsimple.HelpFormatter;
import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import static com.github.fge.jsonschema.main.cli.RetCode.*;

public final class Main
{
    private static final HelpFormatter HELP = new CustomHelpFormatter();

    private static final ObjectMapper MAPPER = JacksonUtils.newMapper();

    private final JsonSchemaFactory factory;
    private final SyntaxValidator syntaxValidator;

    public static void main(final String... args)
        throws IOException, ProcessingException
    {
        final OptionParser parser = new OptionParser();
        parser.accepts("help", "show this help").forHelp();
        parser.acceptsAll(Arrays.asList("s", "brief"),
            "only show validation status (OK/NOT OK)");
        parser.acceptsAll(Arrays.asList("q", "quiet"),
            "no output; exit with the relevant return code (see below)");
        parser.accepts("syntax",
            "check the syntax of schema(s) given as argument(s)");
        parser.accepts("fakeroot",
            "pretend that the current directory is absolute URI \"uri\"")
            .withRequiredArg();
        parser.formatHelpWith(HELP);

        final OptionSet optionSet;
        final boolean isSyntax;
        final int requiredArgs;

        Reporter reporter = Reporters.DEFAULT;
        String fakeRoot = null;

        try {
            optionSet = parser.parse(args);
        } catch (OptionException e) {
            System.err.println("unrecognized option(s): "
                + CustomHelpFormatter.OPTIONS_JOINER.join(e.options()));
            parser.printHelpOn(System.err);
            System.exit(CMD_ERROR.get());
            throw new IllegalStateException("WTF??");
        }

        if (optionSet.has("help")) {
            parser.printHelpOn(System.out);
            System.exit(ALL_OK.get());
        }

        if (optionSet.has("s") && optionSet.has("q")) {
            System.err.println("cannot specify both \"--brief\" and " +
                "\"--quiet\"");
            parser.printHelpOn(System.err);
            System.exit(CMD_ERROR.get());
        }

        if (optionSet.has("fakeroot"))
            fakeRoot = (String) optionSet.valueOf("fakeroot");

        isSyntax = optionSet.has("syntax");
        requiredArgs = isSyntax ? 1 : 2;

        @SuppressWarnings("unchecked")
        final List arguments
            = (List) optionSet.nonOptionArguments();

        if (arguments.size() < requiredArgs) {
            System.err.println("missing arguments");
            parser.printHelpOn(System.err);
            System.exit(CMD_ERROR.get());
        }

        final List files = Lists.newArrayList();
        for (final String target: arguments)
            files.add(new File(target).getCanonicalFile());

        if (optionSet.has("brief"))
            reporter = Reporters.BRIEF;
        else if (optionSet.has("quiet")) {
            System.out.close();
            System.err.close();
            reporter = Reporters.QUIET;
        }

        new Main(fakeRoot).proceed(reporter, files, isSyntax);
    }

    Main(final String fakeRoot)
        throws IOException
    {
        final URITranslatorConfigurationBuilder builder
            = URITranslatorConfiguration.newBuilder()
                .setNamespace(getCwd());
        if (fakeRoot != null)
            builder.addPathRedirect(fakeRoot, getCwd());
        final LoadingConfiguration cfg = LoadingConfiguration.newBuilder()
            .setURITranslatorConfiguration(builder.freeze()).freeze();
        factory = JsonSchemaFactory.newBuilder()
            .setLoadingConfiguration(cfg).freeze();
        syntaxValidator = factory.getSyntaxValidator();
    }

    private void proceed(final Reporter reporter, final List files,
        final boolean isSyntax)
        throws IOException, ProcessingException
    {

        final RetCode retCode = isSyntax ? doSyntax(reporter, files)
            : doValidation(reporter, files);
        System.exit(retCode.get());
    }

    private RetCode doSyntax(final Reporter reporter, final List files)
        throws IOException
    {
        RetCode retcode, ret = ALL_OK;
        String fileName;
        JsonNode node;

        for (final File file: files) {
            fileName = file.toString();
            node = MAPPER.readTree(file);
            retcode = reporter.validateSchema(syntaxValidator, fileName, node);
            if (retcode != ALL_OK)
                ret = retcode;
        }

        return ret;
    }

    private RetCode doValidation(final Reporter reporter,
        final List files)
        throws IOException, ProcessingException
    {
        final File schemaFile = files.remove(0);
        final String uri = schemaFile.toURI().normalize().toString();
        JsonNode node;

        node = MAPPER.readTree(schemaFile);
        if (!syntaxValidator.schemaIsValid(node)) {
            System.err.println("Schema is invalid! Aborting...");
            return SCHEMA_SYNTAX_ERROR;
        }

        final JsonSchema schema = factory.getJsonSchema(uri);

        RetCode ret = ALL_OK, retcode;

        for (final File file: files) {
            node = MAPPER.readTree(file);
            retcode = reporter.validateInstance(schema, file.toString(), node);
            if (retcode != ALL_OK)
                ret = retcode;
        }

        return ret;
    }

    private static String getCwd()
        throws IOException
    {
        final File cwd = new File(System.getProperty("user.dir", "."))
            .getCanonicalFile();
        return URIUtils.normalizeURI(cwd.toURI()).toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy