SLING-8339 - CLI hangs when an unhandled exception occurs

Allow commands to throw exceptions and stop the framework whenever
such an error is thrown.
diff --git a/src/main/java/org/apache/sling/cli/impl/Command.java b/src/main/java/org/apache/sling/cli/impl/Command.java
index 4caeea7..4b015c4 100644
--- a/src/main/java/org/apache/sling/cli/impl/Command.java
+++ b/src/main/java/org/apache/sling/cli/impl/Command.java
@@ -22,5 +22,5 @@
     String PROPERTY_NAME_SUBCOMMAND = "subcommand";
     String PROPERTY_NAME_SUMMARY = "summary";
 
-    void execute(String target);
+    void execute(String target) throws Exception;
 }
diff --git a/src/main/java/org/apache/sling/cli/impl/CommandProcessor.java b/src/main/java/org/apache/sling/cli/impl/CommandProcessor.java
index 57e5430..6ca6bca 100644
--- a/src/main/java/org/apache/sling/cli/impl/CommandProcessor.java
+++ b/src/main/java/org/apache/sling/cli/impl/CommandProcessor.java
@@ -57,16 +57,22 @@
         // TODO - remove duplication from CLI parsing code
         CommandKey key = CommandKey.of(ctx.getProperty("exec.args"));
         String target = parseTarget(ctx.getProperty("exec.args"));
-        commands.getOrDefault(key, new CommandWithProps(ignored -> {
-            logger.info("Usage: sling command sub-command [target]");
-            logger.info("");
-            logger.info("Available commands:");
-            commands.forEach((k, c) -> logger.info("{} {}: {}", k.command, k.subCommand, c.summary));
-        }, "")).cmd.execute(target);
         try {
-            ctx.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(Framework.class).stop();
-        } catch (BundleException e) {
+            commands.getOrDefault(key, new CommandWithProps(ignored -> {
+                logger.info("Usage: sling command sub-command [target]");
+                logger.info("");
+                logger.info("Available commands:");
+                commands.forEach((k, c) -> logger.info("{} {}: {}", k.command, k.subCommand, c.summary));
+            }, "")).cmd.execute(target);
+        } catch (Exception e) {
             logger.warn("Failed running command", e);
+        } finally {
+            try {
+                ctx.getBundle(Constants.SYSTEM_BUNDLE_LOCATION).adapt(Framework.class).stop();
+            } catch (BundleException e) {
+                logger.error("Failed shutting down framework, forcing exit", e);
+                System.exit(1);
+            }
         }
     }