001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package gov.nist.secauto.oscal.tools.cli.core.commands;
007
008import gov.nist.secauto.metaschema.cli.commands.AbstractValidateContentCommand;
009import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
010import gov.nist.secauto.metaschema.cli.processor.ExitCode;
011import gov.nist.secauto.metaschema.cli.processor.command.CommandExecutionException;
012import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor;
013import gov.nist.secauto.metaschema.core.model.IModule;
014import gov.nist.secauto.metaschema.core.model.MetaschemaException;
015import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
016import gov.nist.secauto.metaschema.core.model.validation.JsonSchemaContentValidator;
017import gov.nist.secauto.metaschema.core.model.validation.XmlSchemaContentValidator;
018import gov.nist.secauto.metaschema.databind.IBindingContext;
019import gov.nist.secauto.metaschema.databind.IBindingContext.ISchemaValidationProvider;
020import gov.nist.secauto.oscal.lib.OscalBindingContext;
021import gov.nist.secauto.oscal.lib.model.OscalCompleteModule;
022
023import org.apache.commons.cli.CommandLine;
024import org.json.JSONObject;
025import org.xml.sax.SAXException;
026
027import java.io.IOException;
028import java.net.URL;
029import java.util.Set;
030
031import edu.umd.cs.findbugs.annotations.NonNull;
032
033/**
034 * Used by implementing classes to provide an OSCAL content validation command.
035 */
036public abstract class AbstractOscalValidationCommand
037    extends AbstractValidateContentCommand {
038
039  /**
040   * Load the OSCAL XML schemas.
041   *
042   * @return the XML schema validator instance
043   * @throws IOException
044   *           if an error occurred while parsing the provided XML schemas
045   */
046  @NonNull
047  protected abstract XmlSchemaContentValidator getOscalXmlSchemas() throws IOException;
048
049  /**
050   * Load the OSCAL JSON schemas.
051   *
052   * @return the XML schema validator instance
053   * @throws IOException
054   *           if an error occurred while parsing the provided XML schemas
055   */
056  @NonNull
057  protected abstract JsonSchemaContentValidator getOscalJsonSchema() throws IOException;
058
059  @Override
060  public abstract ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine);
061
062  /**
063   * Provides OSCAL validation command execution support.
064   */
065  protected class OscalValidationCommandExecutor
066      extends AbstractValidateContentCommand.AbstractValidationCommandExecutor
067      implements ISchemaValidationProvider {
068
069    /**
070     * Construct a new command executor.
071     *
072     * @param callingContext
073     *          the context of the command execution
074     * @param commandLine
075     *          the parsed command line details
076     */
077    protected OscalValidationCommandExecutor(
078        @NonNull CallingContext callingContext,
079        @NonNull CommandLine commandLine) {
080      super(callingContext, commandLine);
081    }
082
083    @Override
084    protected IBindingContext getBindingContext(@NonNull Set<IConstraintSet> constraintSets) {
085      return OscalBindingContext.builder()
086          .constraintSet(constraintSets)
087          .build();
088    }
089
090    @Override
091    @NonNull
092    public XmlSchemaContentValidator getXmlSchemas(URL targetResource, IBindingContext bindingContext)
093        throws IOException, SAXException {
094      return getOscalXmlSchemas();
095    }
096
097    @Override
098    @NonNull
099    public JsonSchemaContentValidator getJsonSchema(JSONObject json, IBindingContext bindingContext)
100        throws IOException {
101      return getOscalJsonSchema();
102    }
103
104    @Override
105    @NonNull
106    protected ISchemaValidationProvider getSchemaValidationProvider(
107        @NonNull IModule module,
108        @NonNull CommandLine commandLine,
109        @NonNull IBindingContext bindingContext) {
110      return this;
111    }
112
113    @Override
114    protected IModule getModule(CommandLine commandLine, IBindingContext bindingContext)
115        throws CommandExecutionException {
116      try {
117        return bindingContext.registerModule(OscalCompleteModule.class);
118      } catch (MetaschemaException ex) {
119        throw new CommandExecutionException(ExitCode.PROCESSING_ERROR, "Failed to register OSCAL module", ex);
120      }
121    }
122  }
123}