1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.oscal.tools.cli.core.commands;
7   
8   import gov.nist.secauto.metaschema.cli.commands.AbstractValidateContentCommand;
9   import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
10  import gov.nist.secauto.metaschema.cli.processor.ExitCode;
11  import gov.nist.secauto.metaschema.cli.processor.command.CommandExecutionException;
12  import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor;
13  import gov.nist.secauto.metaschema.core.model.IModule;
14  import gov.nist.secauto.metaschema.core.model.MetaschemaException;
15  import gov.nist.secauto.metaschema.core.model.constraint.IConstraintSet;
16  import gov.nist.secauto.metaschema.core.model.validation.JsonSchemaContentValidator;
17  import gov.nist.secauto.metaschema.core.model.validation.XmlSchemaContentValidator;
18  import gov.nist.secauto.metaschema.databind.IBindingContext;
19  import gov.nist.secauto.metaschema.databind.IBindingContext.ISchemaValidationProvider;
20  import gov.nist.secauto.oscal.lib.OscalBindingContext;
21  import gov.nist.secauto.oscal.lib.model.OscalCompleteModule;
22  
23  import org.apache.commons.cli.CommandLine;
24  import org.json.JSONObject;
25  import org.xml.sax.SAXException;
26  
27  import java.io.IOException;
28  import java.net.URL;
29  import java.util.Set;
30  
31  import edu.umd.cs.findbugs.annotations.NonNull;
32  
33  /**
34   * Used by implementing classes to provide an OSCAL content validation command.
35   */
36  public abstract class AbstractOscalValidationCommand
37      extends AbstractValidateContentCommand {
38  
39    /**
40     * Load the OSCAL XML schemas.
41     *
42     * @return the XML schema validator instance
43     * @throws IOException
44     *           if an error occurred while parsing the provided XML schemas
45     */
46    @NonNull
47    protected abstract XmlSchemaContentValidator getOscalXmlSchemas() throws IOException;
48  
49    /**
50     * Load the OSCAL JSON schemas.
51     *
52     * @return the XML schema validator instance
53     * @throws IOException
54     *           if an error occurred while parsing the provided XML schemas
55     */
56    @NonNull
57    protected abstract JsonSchemaContentValidator getOscalJsonSchema() throws IOException;
58  
59    @Override
60    public abstract ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine);
61  
62    /**
63     * Provides OSCAL validation command execution support.
64     */
65    protected class OscalValidationCommandExecutor
66        extends AbstractValidateContentCommand.AbstractValidationCommandExecutor
67        implements ISchemaValidationProvider {
68  
69      /**
70       * Construct a new command executor.
71       *
72       * @param callingContext
73       *          the context of the command execution
74       * @param commandLine
75       *          the parsed command line details
76       */
77      protected OscalValidationCommandExecutor(
78          @NonNull CallingContext callingContext,
79          @NonNull CommandLine commandLine) {
80        super(callingContext, commandLine);
81      }
82  
83      @Override
84      protected IBindingContext getBindingContext(@NonNull Set<IConstraintSet> constraintSets) {
85        return OscalBindingContext.builder()
86            .constraintSet(constraintSets)
87            .build();
88      }
89  
90      @Override
91      @NonNull
92      public XmlSchemaContentValidator getXmlSchemas(URL targetResource, IBindingContext bindingContext)
93          throws IOException, SAXException {
94        return getOscalXmlSchemas();
95      }
96  
97      @Override
98      @NonNull
99      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 }