Add missing options to requirement-add/-remove, and format the json output repository so that it’s readable
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
index abcff31..9df243b 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/InstallFeatureCommand.java
@@ -31,8 +31,6 @@
@Service
public class InstallFeatureCommand extends FeaturesCommandSupport {
- private static String DEFAULT_VERSION = "0.0.0";
-
@Argument(index = 0, name = "features", description = "The name and version of the features to install. A feature id looks like name/version. The version is optional.", required = true, multiValued = true)
@Completion(AvailableFeatureCompleter.class)
List<String> features;
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RequirementAdd.java b/features/command/src/main/java/org/apache/karaf/features/command/RequirementAdd.java
index 12b8917..78a6289 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/RequirementAdd.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RequirementAdd.java
@@ -50,6 +50,15 @@
@Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only")
boolean simulate;
+ @Option(name = "--store", description = "Store the resolution into the given file and result for offline analysis")
+ String outputFile;
+
+ @Option(name = "--features-wiring", description = "Print the wiring between features")
+ boolean featuresWiring;
+
+ @Option(name = "--all-wiring", description = "Print the full wiring")
+ boolean allWiring;
+
@Option(name = "-g", aliases = "--region", description = "Region to install to")
String region = FeaturesService.ROOT_REGION;
@@ -60,8 +69,11 @@
addOption(FeaturesService.Option.NoAutoRefreshBundles, noRefresh);
addOption(FeaturesService.Option.NoAutoManageBundles, noManage);
addOption(FeaturesService.Option.Verbose, verbose);
+ addOption(FeaturesService.Option.DisplayFeaturesWiring, featuresWiring);
+ addOption(FeaturesService.Option.DisplayAllWiring, allWiring);
Map<String, Set<String>> reqs = new HashMap<>();
reqs.put(region, new HashSet<>(requirements));
+ featuresService.setResolutionOutputFile(outputFile);
featuresService.addRequirements(reqs, options);
}
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/RequirementRemove.java b/features/command/src/main/java/org/apache/karaf/features/command/RequirementRemove.java
index ad800e0..11f700b 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/RequirementRemove.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/RequirementRemove.java
@@ -50,6 +50,15 @@
@Option(name = "-t", aliases = "--simulate", description = "Perform a simulation only")
boolean simulate;
+ @Option(name = "--store", description = "Store the resolution into the given file and result for offline analysis")
+ String outputFile;
+
+ @Option(name = "--features-wiring", description = "Print the wiring between features")
+ boolean featuresWiring;
+
+ @Option(name = "--all-wiring", description = "Print the full wiring")
+ boolean allWiring;
+
@Option(name = "-g", aliases = "--region", description = "Region to apply to")
String region = FeaturesService.ROOT_REGION;
@@ -60,8 +69,11 @@
addOption(FeaturesService.Option.NoAutoRefreshBundles, noRefresh);
addOption(FeaturesService.Option.NoAutoManageBundles, noManage);
addOption(FeaturesService.Option.Verbose, verbose);
+ addOption(FeaturesService.Option.DisplayFeaturesWiring, featuresWiring);
+ addOption(FeaturesService.Option.DisplayAllWiring, allWiring);
Map<String, Set<String>> reqs = new HashMap<>();
reqs.put(region, new HashSet<>(requirements));
+ featuresService.setResolutionOutputFile(outputFile);
featuresService.removeRequirements(reqs, options);
}
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
index d162e9e..3f83733 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/region/SubsystemResolver.java
@@ -209,7 +209,7 @@
Paths.get(outputFile),
StandardCharsets.UTF_8,
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
- JsonWriter.write(writer, json);
+ JsonWriter.write(writer, json, true);
}
}
} else {
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
index fb27346..b65ea27 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/util/JsonWriter.java
@@ -20,6 +20,7 @@
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
@@ -31,16 +32,29 @@
}
public static void write(OutputStream stream, Object value) throws IOException {
+ write(stream, value, false);
+ }
+
+ public static void write(OutputStream stream, Object value, boolean format) throws IOException {
Writer writer = new OutputStreamWriter(stream);
- write(writer, value);
+ write(writer, value, format);
writer.flush();
}
public static void write(Writer writer, Object value) throws IOException {
+ write(writer, value, false);
+ }
+
+ public static void write(Writer writer, Object value, boolean format) throws IOException {
+ int indent = format ? 0 : -1;
+ write(writer, value, indent);
+ }
+
+ private static void write(Writer writer, Object value, int indent) throws IOException {
if (value instanceof Map) {
- writeObject(writer, (Map) value);
+ writeObject(writer, (Map) value, indent);
} else if (value instanceof Collection) {
- writeArray(writer, (Collection) value);
+ writeArray(writer, (Collection) value, indent);
} else if (value instanceof Number) {
writeNumber(writer, (Number) value);
} else if (value instanceof String) {
@@ -54,7 +68,7 @@
}
}
- private static void writeObject(Writer writer, Map<?, ?> value) throws IOException {
+ private static void writeObject(Writer writer, Map<?, ?> value, int indent) throws IOException {
writer.append('{');
boolean first = true;
for (Map.Entry entry : value.entrySet()) {
@@ -63,9 +77,21 @@
} else {
first = false;
}
+ if (indent >= 0) {
+ indent(writer, indent + 1);
+ }
writeString(writer, (String) entry.getKey());
+ if (indent >= 0) {
+ writer.append(' ');
+ }
writer.append(':');
- write(writer, entry.getValue());
+ if (indent >= 0) {
+ writer.append(' ');
+ }
+ write(writer, entry.getValue(), indent + 1);
+ }
+ if (indent >= 0) {
+ indent(writer, indent);
}
writer.append('}');
}
@@ -122,7 +148,7 @@
writer.append(Boolean.toString(value));
}
- private static void writeArray(Writer writer, Collection<?> value) throws IOException {
+ private static void writeArray(Writer writer, Collection<?> value, int indent) throws IOException {
writer.append('[');
boolean first = true;
for (Object obj : value) {
@@ -131,7 +157,13 @@
} else {
first = false;
}
- write(writer, obj);
+ if (indent >= 0) {
+ indent(writer, indent + 1);
+ }
+ write(writer, obj, indent + 1);
+ }
+ if (indent >= 0) {
+ indent(writer, indent);
}
writer.append(']');
}
@@ -139,4 +171,20 @@
private static void writeNull(Writer writer) throws IOException {
writer.append("null");
}
+
+ static char[] INDENT;
+ static {
+ INDENT = new char[1];
+ Arrays.fill(INDENT, '\t');
+ }
+
+ private static void indent(Writer writer, int indent) throws IOException {
+ writer.write("\n");
+ while (indent > INDENT.length) {
+ char[] a = new char[INDENT.length * 2];
+ Arrays.fill(a, '\t');
+ INDENT = a;
+ }
+ writer.write(INDENT, 0, indent);
+ }
}