4646 Main .Search .class ,
4747 Main .Install .class ,
4848 Main .PrintPath .class ,
49- Main .Do .class
49+ Main .Do .class ,
50+ Main .Clean .class ,
51+ Main .Build .class ,
52+ Main .Run .class ,
53+ Main .Test .class
5054 })
5155public class Main {
5256
@@ -72,8 +76,8 @@ static class Copy implements Callable<Integer> {
7276 public Integer call () throws Exception {
7377 SyncStats stats =
7478 Jpm .builder ()
75- .directory (artifactsMixin .copyMixin .directory )
76- .noLinks (artifactsMixin .copyMixin .noLinks )
79+ .directory (artifactsMixin .depsMixin .directory )
80+ .noLinks (artifactsMixin .depsMixin .noLinks )
7781 .build ()
7882 .copy (artifactsMixin .artifactNames , sync );
7983 if (!quietMixin .quiet ) {
@@ -94,7 +98,7 @@ public Integer call() throws Exception {
9498 + "Example:\n jpm search httpclient\n " )
9599 static class Search implements Callable <Integer > {
96100 @ Mixin QuietMixin quietMixin ;
97- @ Mixin CopyMixin copyMixin ;
101+ @ Mixin DepsMixin depsMixin ;
98102
99103 @ Option (
100104 names = {"-i" , "--interactive" },
@@ -133,8 +137,8 @@ public Integer call() throws Exception {
133137 if ("install" .equals (artifactAction )) {
134138 SyncStats stats =
135139 Jpm .builder ()
136- .directory (copyMixin .directory )
137- .noLinks (copyMixin .noLinks )
140+ .directory (depsMixin .directory )
141+ .noLinks (depsMixin .noLinks )
138142 .build ()
139143 .install (new String [] {selectedArtifact });
140144 if (!quietMixin .quiet ) {
@@ -143,8 +147,8 @@ public Integer call() throws Exception {
143147 } else if ("copy" .equals (artifactAction )) {
144148 SyncStats stats =
145149 Jpm .builder ()
146- .directory (copyMixin .directory )
147- .noLinks (copyMixin .noLinks )
150+ .directory (depsMixin .directory )
151+ .noLinks (depsMixin .noLinks )
148152 .build ()
149153 .copy (new String [] {selectedArtifact }, false );
150154 if (!quietMixin .quiet ) {
@@ -175,8 +179,8 @@ public Integer call() throws Exception {
175179 String [] search (String artifactPattern ) {
176180 try {
177181 return Jpm .builder ()
178- .directory (copyMixin .directory )
179- .noLinks (copyMixin .noLinks )
182+ .directory (depsMixin .directory )
183+ .noLinks (depsMixin .noLinks )
180184 .build ()
181185 .search (artifactPattern , Math .min (max , 200 ));
182186 } catch (IOException e ) {
@@ -272,8 +276,8 @@ static class Install implements Callable<Integer> {
272276 public Integer call () throws Exception {
273277 SyncStats stats =
274278 Jpm .builder ()
275- .directory (optionalArtifactsMixin .copyMixin .directory )
276- .noLinks (optionalArtifactsMixin .copyMixin .noLinks )
279+ .directory (optionalArtifactsMixin .depsMixin .directory )
280+ .noLinks (optionalArtifactsMixin .depsMixin .noLinks )
277281 .build ()
278282 .install (optionalArtifactsMixin .artifactNames );
279283 if (!quietMixin .quiet ) {
@@ -297,8 +301,8 @@ static class PrintPath implements Callable<Integer> {
297301 public Integer call () throws Exception {
298302 List <Path > files =
299303 Jpm .builder ()
300- .directory (optionalArtifactsMixin .copyMixin .directory )
301- .noLinks (optionalArtifactsMixin .copyMixin .noLinks )
304+ .directory (optionalArtifactsMixin .depsMixin .directory )
305+ .noLinks (optionalArtifactsMixin .depsMixin .noLinks )
302306 .build ()
303307 .path (optionalArtifactsMixin .artifactNames );
304308 if (!files .isEmpty ()) {
@@ -318,7 +322,7 @@ public Integer call() throws Exception {
318322 "Executes an action command defined in the app.yml file. Actions can use variable substitution for classpath.\n \n "
319323 + "Example:\n jpm do build\n jpm do test\n " )
320324 static class Do implements Callable <Integer > {
321- @ Mixin CopyMixin copyMixin ;
325+ @ Mixin DepsMixin depsMixin ;
322326
323327 @ Option (
324328 names = {"-l" , "--list" },
@@ -327,19 +331,28 @@ static class Do implements Callable<Integer> {
327331 private boolean list ;
328332
329333 @ Parameters (
330- paramLabel = "actionName " ,
334+ paramLabel = "action " ,
331335 description = "Name of the action to execute as defined in app.yml" ,
332- arity = "0..1" )
336+ arity = "0..*" ,
337+ index = "0" )
333338 private String actionName ;
334339
340+ @ Parameters (
341+ paramLabel = "actionsAndArguments" ,
342+ description =
343+ "Optional additional actions and/or arguments to be passed to the action(s)" ,
344+ arity = "0..*" ,
345+ index = "1..*" )
346+ private ArrayList <String > actsAndArgs = new ArrayList <>();
347+
335348 @ Override
336349 public Integer call () throws Exception {
337350 try {
338351 if (list ) {
339352 List <String > actionNames =
340353 Jpm .builder ()
341- .directory (copyMixin .directory )
342- .noLinks (copyMixin .noLinks )
354+ .directory (depsMixin .directory )
355+ .noLinks (depsMixin .noLinks )
343356 .build ()
344357 .listActions ();
345358 if (actionNames .isEmpty ()) {
@@ -348,22 +361,118 @@ public Integer call() throws Exception {
348361 System .out .println ("Available actions:" );
349362 actionNames .forEach (n -> System .out .println (" " + n ));
350363 }
351- return 0 ;
352364 } else {
353- return Jpm .builder ()
354- .directory (copyMixin .directory )
355- .noLinks (copyMixin .noLinks )
356- .build ()
357- .executeAction (actionName );
365+ if (actionName == null || actionName .isEmpty ()) {
366+ System .err .println (
367+ "Action name is required. Use --list to see available actions." );
368+ return 1 ;
369+ }
370+ // Split the full arguments list in multiple actions and their arguments
371+ int idx = 0 ;
372+ actsAndArgs .add (0 , actionName );
373+ while (idx < actsAndArgs .size ()) {
374+ String action = actsAndArgs .get (idx );
375+ if (action .startsWith ("-" )) {
376+ System .err .println (
377+ "Unexpected argument, was expecting an action name: " + action );
378+ return 1 ;
379+ }
380+ idx ++;
381+ List <String > args = new ArrayList <>();
382+ while (idx < actsAndArgs .size () && actsAndArgs .get (idx ).startsWith ("-" )) {
383+ String opt = actsAndArgs .get (idx );
384+ if (opt .equals ("-a" ) || opt .equals ("--arg" )) {
385+ args .add (actsAndArgs .get (++idx ));
386+ } else if (opt .startsWith ("-a=" ) || opt .startsWith ("--arg=" )) {
387+ args .add (opt .substring (opt .indexOf ('=' ) + 1 ));
388+ } else {
389+ System .err .println (
390+ "Unexpected argument, was expecting an action argument like '-a' or '--arg', not: "
391+ + opt );
392+ return 1 ;
393+ }
394+ idx ++;
395+ }
396+ int exitCode =
397+ Jpm .builder ()
398+ .directory (depsMixin .directory )
399+ .noLinks (depsMixin .noLinks )
400+ .build ()
401+ .executeAction (action , args );
402+ if (exitCode != 0 ) {
403+ return exitCode ;
404+ }
405+ }
358406 }
359407 } catch (Exception e ) {
360408 System .err .println (e .getMessage ());
361409 return 1 ;
362410 }
411+ return 0 ;
412+ }
413+ }
414+
415+ abstract static class DoAlias implements Callable <Integer > {
416+ @ Mixin DoAliasMixin doAliasMixin ;
417+
418+ abstract String actionName ();
419+
420+ @ Override
421+ public Integer call () throws Exception {
422+ try {
423+ return Jpm .builder ()
424+ .directory (doAliasMixin .depsMixin .directory )
425+ .noLinks (doAliasMixin .depsMixin .noLinks )
426+ .build ()
427+ .executeAction (actionName (), doAliasMixin .args );
428+ } catch (Exception e ) {
429+ System .err .println (e .getMessage ());
430+ return 1 ;
431+ }
432+ }
433+ }
434+
435+ @ Command (
436+ name = "clean" ,
437+ description = "Executes the 'clean' action as defined in the app.yml file." )
438+ static class Clean extends DoAlias {
439+ @ Override
440+ String actionName () {
441+ return "clean" ;
442+ }
443+ }
444+
445+ @ Command (
446+ name = "build" ,
447+ description = "Executes the 'build' action as defined in the app.yml file." )
448+ static class Build extends DoAlias {
449+ @ Override
450+ String actionName () {
451+ return "build" ;
452+ }
453+ }
454+
455+ @ Command (
456+ name = "run" ,
457+ description = "Executes the 'run' action as defined in the app.yml file." )
458+ static class Run extends DoAlias {
459+ @ Override
460+ String actionName () {
461+ return "run" ;
462+ }
463+ }
464+
465+ @ Command (
466+ name = "test" ,
467+ description = "Executes the 'test' action as defined in the app.yml file." )
468+ static class Test extends DoAlias {
469+ @ Override
470+ String actionName () {
471+ return "test" ;
363472 }
364473 }
365474
366- static class CopyMixin {
475+ static class DepsMixin {
367476 @ Option (
368477 names = {"-d" , "--directory" },
369478 description = "Directory to copy artifacts to" ,
@@ -377,8 +486,20 @@ static class CopyMixin {
377486 boolean noLinks ;
378487 }
379488
489+ static class DoAliasMixin {
490+ @ Mixin DepsMixin depsMixin ;
491+
492+ @ Parameters (
493+ paramLabel = "arguments" ,
494+ description =
495+ "Optional arguments to be passed to the action" ,
496+ arity = "0..*" ,
497+ index = "0..*" )
498+ ArrayList <String > args = new ArrayList <>();
499+ }
500+
380501 static class ArtifactsMixin {
381- @ Mixin CopyMixin copyMixin ;
502+ @ Mixin DepsMixin depsMixin ;
382503
383504 @ Parameters (
384505 paramLabel = "artifacts" ,
@@ -389,7 +510,7 @@ static class ArtifactsMixin {
389510 }
390511
391512 static class OptionalArtifactsMixin {
392- @ Mixin CopyMixin copyMixin ;
513+ @ Mixin DepsMixin depsMixin ;
393514
394515 @ Parameters (
395516 paramLabel = "artifacts" ,
@@ -413,30 +534,19 @@ private static void printStats(SyncStats stats) {
413534 (Integer ) stats .copied , (Integer ) stats .updated , (Integer ) stats .deleted );
414535 }
415536
537+ public static CommandLine getCommandLine () {
538+ return new CommandLine (new Main ())
539+ .setStopAtPositional (true )
540+ .setAllowOptionsAsOptionParameters (true )
541+ .setAllowSubcommandsAsOptionParameters (true );
542+ }
543+
416544 /**
417545 * Main entry point for the jpm command line tool.
418546 *
419547 * @param args The command line arguments.
420548 */
421549 public static void main (String ... args ) {
422- if (args .length == 0 ) {
423- System .err .println (
424- "Running 'jpm search --interactive', try 'jpm --help' for more options" );
425- args = new String [] {"search" , "--interactive" };
426- }
427-
428- // Handle common aliases
429- if (args .length > 0 ) {
430- String firstArg = args [0 ];
431- if ("build" .equals (firstArg ) || "test" .equals (firstArg ) || "run" .equals (firstArg )) {
432- // Convert "jpm build", "jpm test", "jpm run" to "jpm do <command>"
433- String [] newArgs = new String [args .length + 1 ];
434- newArgs [0 ] = "do" ;
435- System .arraycopy (args , 0 , newArgs , 1 , args .length );
436- args = newArgs ;
437- }
438- }
439-
440- new CommandLine (new Main ()).execute (args );
550+ getCommandLine ().execute (args );
441551 }
442552}
0 commit comments