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.AbstractConvertSubcommand;
9   import gov.nist.secauto.metaschema.cli.processor.CLIProcessor.CallingContext;
10  import gov.nist.secauto.metaschema.cli.processor.command.ICommandExecutor;
11  import gov.nist.secauto.metaschema.core.model.IBoundObject;
12  import gov.nist.secauto.metaschema.databind.IBindingContext;
13  import gov.nist.secauto.metaschema.databind.io.Format;
14  import gov.nist.secauto.metaschema.databind.io.FormatDetector;
15  import gov.nist.secauto.metaschema.databind.io.IBoundLoader;
16  import gov.nist.secauto.metaschema.databind.io.ISerializer;
17  import gov.nist.secauto.metaschema.databind.io.ModelDetector;
18  import gov.nist.secauto.oscal.lib.OscalBindingContext;
19  
20  import org.apache.commons.cli.CommandLine;
21  
22  import java.io.FileNotFoundException;
23  import java.io.IOException;
24  import java.io.InputStream;
25  import java.io.Writer;
26  import java.net.URI;
27  
28  import edu.umd.cs.findbugs.annotations.NonNull;
29  
30  public class ConvertCommand
31      extends AbstractConvertSubcommand {
32    @Override
33    public String getDescription() {
34      return "Check that the specified OSCAL instance is well-formed and valid to an OSCAL model.";
35    }
36  
37    @Override
38    public ICommandExecutor newExecutor(CallingContext callingContext, CommandLine commandLine) {
39      return new OscalCommandExecutor(callingContext, commandLine);
40    }
41  
42    private static final class OscalCommandExecutor
43        extends AbstractConversionCommandExecutor {
44  
45      private OscalCommandExecutor(
46          @NonNull CallingContext callingContext,
47          @NonNull CommandLine commandLine) {
48        super(callingContext, commandLine);
49      }
50  
51      @Override
52      protected IBindingContext getBindingContext() {
53        return OscalBindingContext.instance();
54      }
55  
56      @Override
57      protected void handleConversion(URI source, Format toFormat, Writer writer, IBoundLoader loader)
58          throws FileNotFoundException, IOException {
59  
60        Class<? extends IBoundObject> boundClass;
61        IBoundObject object;
62        try (InputStream is = source.toURL().openStream()) {
63          FormatDetector.Result formatResult = loader.detectFormat(is);
64          Format sourceformat = formatResult.getFormat();
65          try (InputStream fis = formatResult.getDataStream()) {
66            try (ModelDetector.Result modelResult = loader.detectModel(fis, sourceformat)) {
67              boundClass = modelResult.getBoundClass();
68              try (InputStream mis = modelResult.getDataStream()) {
69                object = loader.load(boundClass, sourceformat, mis, source);
70              }
71            }
72          }
73        }
74        ISerializer<?> serializer = getBindingContext().newSerializer(toFormat, boundClass);
75        serializer.serialize(object, writer);
76      }
77    }
78  }