com.github.fge.jsonschema.main.cli.Main Maven / Gradle / Ivy
/*
* 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