1313 * See the License for the specific language governing permissions and
1414 * limitations under the License.
1515 */
16- package com .redhat .exhort ;
16+ package com .redhat .exhort .cli ;
17+
18+ import static com .redhat .exhort .cli .AppUtils .exitWithError ;
19+ import static com .redhat .exhort .cli .AppUtils .printException ;
20+ import static com .redhat .exhort .cli .AppUtils .printLine ;
1721
1822import com .fasterxml .jackson .annotation .JsonInclude ;
1923import com .fasterxml .jackson .core .JsonProcessingException ;
2024import com .fasterxml .jackson .databind .ObjectMapper ;
25+ import com .redhat .exhort .Api ;
2126import com .redhat .exhort .api .v4 .AnalysisReport ;
2227import com .redhat .exhort .api .v4 .ProviderReport ;
2328import com .redhat .exhort .api .v4 .Source ;
2934import java .util .concurrent .CompletableFuture ;
3035import java .util .concurrent .ExecutionException ;
3136
32- public class Cli {
37+ public class App {
3338
3439 private static final ObjectMapper MAPPER = new ObjectMapper ();
40+ private static final String CLI_HELPTXT = "cli_help.txt" ;
3541
3642 static {
3743 MAPPER .setSerializationInclusion (JsonInclude .Include .NON_NULL );
3844 }
3945
40- private enum Command {
41- STACK ,
42- COMPONENT
43- }
44-
45- private enum OutputFormat {
46- JSON ,
47- SUMMARY ,
48- HTML
49- }
50-
5146 public static void main (String [] args ) {
5247 if (args .length == 0 || isHelpRequested (args )) {
5348 printHelp ();
@@ -57,15 +52,14 @@ public static void main(String[] args) {
5752 try {
5853 CliArgs cliArgs = parseArgs (args );
5954 String result = executeCommand (cliArgs ).get ();
60- System . out . println (result );
55+ printLine (result );
6156 } catch (IllegalArgumentException e ) {
62- System .err .println ("Error: " + e .getMessage ());
63- System .err .println ();
57+ printException (e );
6458 printHelp ();
65- System . exit ( 1 );
59+ exitWithError ( );
6660 } catch (IOException | InterruptedException | ExecutionException e ) {
67- System . err . println ( "Unexpected error: " + e . getMessage () );
68- System . exit ( 1 );
61+ printException ( e );
62+ exitWithError ( );
6963 }
7064 }
7165
@@ -83,56 +77,58 @@ private static CliArgs parseArgs(String[] args) {
8377 throw new IllegalArgumentException ("Missing required arguments" );
8478 }
8579
86- String commandStr = args [0 ].toLowerCase ();
87- Command command ;
80+ Command command = parseCommand (args [0 ]);
81+
82+ Path path = validateFile (args [1 ]);
8883
84+ OutputFormat outputFormat = parseOutputFormat (command , args [2 ]);
85+
86+ return new CliArgs (command , path , outputFormat );
87+ }
88+
89+ private static Command parseCommand (String commandStr ) {
8990 switch (commandStr ) {
9091 case "stack" :
91- command = Command .STACK ;
92- break ;
92+ return Command .STACK ;
9393 case "component" :
94- command = Command .COMPONENT ;
95- break ;
94+ return Command .COMPONENT ;
9695 default :
9796 throw new IllegalArgumentException (
9897 "Unknown command: " + commandStr + ". Use 'stack' or 'component'" );
9998 }
99+ }
100100
101- String filePath = args [1 ];
102- Path path = Paths .get (filePath );
101+ private static OutputFormat parseOutputFormat (Command command , String formatArg ) {
102+ if (formatArg == null ) {
103+ return OutputFormat .JSON ;
104+ }
105+
106+ switch (formatArg ) {
107+ case "--summary" :
108+ return OutputFormat .SUMMARY ;
109+ case "--html" :
110+ if (command != Command .STACK ) {
111+ throw new IllegalArgumentException ("HTML format is only supported for stack command" );
112+ }
113+ return OutputFormat .HTML ;
114+ default :
115+ throw new IllegalArgumentException (
116+ "Unknown option for " + command + " command: " + formatArg );
117+ }
118+ }
103119
120+ private static Path validateFile (String filePath ) {
121+ Path path = Paths .get (filePath );
104122 if (!Files .exists (path )) {
105123 throw new IllegalArgumentException ("File does not exist: " + filePath );
106124 }
107-
108125 if (!Files .isRegularFile (path )) {
109- throw new IllegalArgumentException ("Path is not a file: " + filePath );
126+ throw new IllegalArgumentException ("File is not a regular file: " + filePath );
110127 }
111-
112- OutputFormat outputFormat = OutputFormat .JSON ; // default
113-
114- // Parse additional options for stack command
115- if (args .length > 2 ) {
116- for (int i = 2 ; i < args .length ; i ++) {
117- switch (args [i ]) {
118- case "--summary" :
119- outputFormat = OutputFormat .SUMMARY ;
120- break ;
121- case "--html" :
122- if (command != Command .STACK ) {
123- throw new IllegalArgumentException ("HTML format is only supported for stack command" );
124- }
125- outputFormat = OutputFormat .HTML ;
126- break ;
127- default :
128- throw new IllegalArgumentException ("Unknown option for stack command: " + args [i ]);
129- }
130- }
131- } else if (command == Command .COMPONENT && args .length > 2 ) {
132- throw new IllegalArgumentException ("Component command does not accept additional options" );
128+ if (!Files .isReadable (path )) {
129+ throw new IllegalArgumentException ("File is not readable: " + filePath );
133130 }
134-
135- return new CliArgs (command , path , outputFormat );
131+ return path ;
136132 }
137133
138134 private static CompletableFuture <String > executeCommand (CliArgs args ) throws IOException {
@@ -152,13 +148,13 @@ private static CompletableFuture<String> executeStackAnalysis(
152148 Api api = new ExhortApi ();
153149 switch (outputFormat ) {
154150 case JSON :
155- return api .stackAnalysis (filePath ).thenApply (Cli ::toJsonString );
151+ return api .stackAnalysis (filePath ).thenApply (App ::toJsonString );
156152 case HTML :
157153 return api .stackAnalysisHtml (filePath ).thenApply (bytes -> new String (bytes ));
158154 case SUMMARY :
159155 return api .stackAnalysis (filePath )
160- .thenApply (Cli ::extractSummary )
161- .thenApply (Cli ::toJsonString );
156+ .thenApply (App ::extractSummary )
157+ .thenApply (App ::toJsonString );
162158 default :
163159 throw new AssertionError ();
164160 }
@@ -169,9 +165,9 @@ private static CompletableFuture<String> executeComponentAnalysis(
169165 Api api = new ExhortApi ();
170166 CompletableFuture <AnalysisReport > analysis = api .componentAnalysis (filePath );
171167 if (outputFormat .equals (OutputFormat .SUMMARY )) {
172- analysis = analysis .thenApply (Cli ::extractSummary );
168+ analysis = analysis .thenApply (App ::extractSummary );
173169 }
174- return analysis .thenApply (Cli ::toJsonString );
170+ return analysis .thenApply (App ::toJsonString );
175171 }
176172
177173 private static String toJsonString (Object obj ) {
@@ -213,44 +209,16 @@ private static AnalysisReport extractSummary(AnalysisReport report) {
213209 }
214210
215211 private static void printHelp () {
216- System .out .println ("Exhort Java API CLI" );
217- System .out .println ();
218- System .out .println ("USAGE:" );
219- System .out .println (" java -jar exhort-java-api.jar <COMMAND> <FILE_PATH> [OPTIONS]" );
220- System .out .println ();
221- System .out .println ("COMMANDS:" );
222- System .out .println (" stack <file_path> [--summary|--html]" );
223- System .out .println (" Perform stack analysis on the specified manifest file" );
224- System .out .println (" Options:" );
225- System .out .println (" --summary Output summary in JSON format" );
226- System .out .println (" --html Output full report in HTML format" );
227- System .out .println (" (default) Output full report in JSON format" );
228- System .out .println ();
229- System .out .println (" component <file_path> [--summary]" );
230- System .out .println (" Perform component analysis on the specified manifest file" );
231- System .out .println (" Options:" );
232- System .out .println (" --summary Output summary in JSON format" );
233- System .out .println (" (default) Output full report in JSON format" );
234- System .out .println ();
235- System .out .println ("OPTIONS:" );
236- System .out .println (" -h, --help Show this help message" );
237- System .out .println ();
238- System .out .println ("EXAMPLES:" );
239- System .out .println (" java -jar exhort-java-api.jar stack /path/to/pom.xml" );
240- System .out .println (" java -jar exhort-java-api.jar stack /path/to/package.json --summary" );
241- System .out .println (" java -jar exhort-java-api.jar stack /path/to/build.gradle --html" );
242- System .out .println (" java -jar exhort-java-api.jar component /path/to/requirements.txt" );
243- }
244-
245- private static class CliArgs {
246- final Command command ;
247- final Path filePath ;
248- final OutputFormat outputFormat ;
212+ try (var inputStream = App .class .getClassLoader ().getResourceAsStream (CLI_HELPTXT )) {
213+ if (inputStream == null ) {
214+ AppUtils .printError ("Help file not found." );
215+ return ;
216+ }
249217
250- CliArgs ( Command command , Path filePath , OutputFormat outputFormat ) {
251- this . command = command ;
252- this . filePath = filePath ;
253- this . outputFormat = outputFormat ;
218+ String helpText = new String ( inputStream . readAllBytes ());
219+ printLine ( helpText ) ;
220+ } catch ( IOException e ) {
221+ AppUtils . printError ( "Error reading help file: " + e . getMessage ()) ;
254222 }
255223 }
256224}
0 commit comments