You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2017/10/04 15:49:40 UTC
[3/3] karaf git commit: [KARAF-5407] Allow feature:info to print the
xml for a given feature
[KARAF-5407] Allow feature:info to print the xml for a given feature
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/880b838c
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/880b838c
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/880b838c
Branch: refs/heads/master
Commit: 880b838cb014120eb327f51baf37887a4ede6d9c
Parents: d586939
Author: Guillaume Nodet <gn...@gmail.com>
Authored: Wed Oct 4 16:09:37 2017 +0200
Committer: Guillaume Nodet <gn...@gmail.com>
Committed: Wed Oct 4 16:55:33 2017 +0200
----------------------------------------------------------------------
features/command/pom.xml | 4 +
.../features/command/InfoFeatureCommand.java | 117 ++++++++++++++++++-
.../apache/karaf/features/FeaturesService.java | 2 +
.../features/internal/model/Dependency.java | 12 +-
.../internal/service/FeaturesServiceImpl.java | 24 ++++
5 files changed, 149 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/880b838c/features/command/pom.xml
----------------------------------------------------------------------
diff --git a/features/command/pom.xml b/features/command/pom.xml
index 9a02a27..d258d37 100644
--- a/features/command/pom.xml
+++ b/features/command/pom.xml
@@ -57,6 +57,10 @@
<artifactId>org.apache.karaf.shell.core</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.eclipse.equinox</groupId>
<artifactId>org.eclipse.equinox.region</artifactId>
<scope>provided</scope>
http://git-wip-us.apache.org/repos/asf/karaf/blob/880b838c/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
index a6cdccd..1ecc0a0 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/InfoFeatureCommand.java
@@ -16,9 +16,17 @@
*/
package org.apache.karaf.features.command;
+import java.util.Arrays;
+import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import org.apache.felix.service.command.Process;
import org.apache.karaf.features.BundleInfo;
import org.apache.karaf.features.Conditional;
import org.apache.karaf.features.ConfigFileInfo;
@@ -31,12 +39,19 @@ import org.apache.karaf.shell.api.action.Argument;
import org.apache.karaf.shell.api.action.Command;
import org.apache.karaf.shell.api.action.Completion;
import org.apache.karaf.shell.api.action.Option;
+import org.apache.karaf.shell.api.action.lifecycle.Reference;
import org.apache.karaf.shell.api.action.lifecycle.Service;
+import org.apache.karaf.shell.api.console.Session;
+import org.jline.terminal.Terminal;
+import org.jline.utils.AttributedStringBuilder;
+import org.jline.utils.AttributedStyle;
@Command(scope = "feature", name = "info", description = "Shows information about selected feature.")
@Service
public class InfoFeatureCommand extends FeaturesCommandSupport {
+ public static final String DEFAULT_XML_COLORS = "el=34;1:at=36;1:av=32;1:cm=37:cd=37";
+
private static final String INDENT = " ";
private static final String FEATURE_CONTENT = "Feature";
private static final String CONDITIONAL_CONTENT = "Conditional(%s)";
@@ -63,6 +78,15 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
@Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false)
private boolean tree;
+ @Option(name = "-x", aliases={"--xml"}, description="Display feature xml", required = false, multiValued = false)
+ private boolean xml;
+
+ @Option(name = "--color", description="Colorize output (`always', `never' or `auto')", required = false, multiValued = false)
+ private String color;
+
+ @Reference
+ Session session;
+
protected void doExecute(FeaturesService admin) throws Exception {
Feature[] features = null;
@@ -77,8 +101,39 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
return;
}
+ if (xml) {
+ boolean colored;
+ switch (color != null ? color : "auto") {
+ case "always":
+ case "yes":
+ case "force":
+ colored = true;
+ break;
+ case "never":
+ case "no":
+ case "none":
+ colored = false;
+ break;
+ case "auto":
+ case "tty":
+ case "if-tty":
+ colored = Process.Utils.current().isTty(1);
+ break;
+ default:
+ throw new IllegalArgumentException("invalid argument ‘" + color + "’ for ‘--color’");
+ }
+ for (Feature feature : features) {
+ String xml = admin.getFeatureXml(feature);
+ if (colored) {
+ xml = colorize(session, xml);
+ }
+ System.out.println(xml);
+ }
+ return;
+ }
+
// default behavior
- if (!config && !dependency && !bundle && !conditional) {
+ if (!config && !dependency && !bundle && !conditional && !tree) {
config = true;
dependency = true;
bundle = true;
@@ -121,7 +176,7 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
}
if (tree) {
- if (config || dependency || bundle) {
+ if (config || dependency || bundle || conditional) {
System.out.println("\nFeature tree");
}
@@ -241,7 +296,7 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
prefix += " ";
List<Dependency> dependencies = resolved.getDependencies();
for (Dependency toDisplay : dependencies) {
- unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix + 1);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix);
}
if (conditional) {
@@ -249,7 +304,7 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
List<Dependency> conditionDependencies = cond.getDependencies();
for (int i = 0, j = conditionDependencies.size(); i < j; i++) {
Dependency toDisplay = dependencies.get(i);
- unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix + 1);
+ unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix);
}
}
}
@@ -295,4 +350,58 @@ public class InfoFeatureCommand extends FeaturesCommandSupport {
return sb.toString();
}
+ private static Map<String, String> getColorMap(Session session, String name, String def) {
+ Object obj = session.get(name + "_COLORS");
+ String str = obj != null ? obj.toString() : null;
+ if (str == null || !str.matches("[a-z]{2}=[0-9]*(;[0-9]+)*(:[a-z]{2}=[0-9]*(;[0-9]+)*)*")) {
+ str = def;
+ }
+ return Arrays.stream(str.split(":"))
+ .collect(Collectors.toMap(s -> s.substring(0, s.indexOf('=')),
+ s -> s.substring(s.indexOf('=') + 1)));
+ }
+
+ private static String colorize(Session session, String xml) {
+ Terminal terminal = (Terminal) session.get(".jline.terminal");
+ Map<String, String> colorMap = getColorMap(session, "XML", DEFAULT_XML_COLORS);
+ Map<Pattern, String> patternColors = new LinkedHashMap<>();
+ patternColors.put(Pattern.compile("(</?[a-z]*)\\s?>?"), "el");
+ patternColors.put(Pattern.compile("(/?>)"), "el");
+ patternColors.put(Pattern.compile("\\s([a-z-]*)\\="), "at");
+ patternColors.put(Pattern.compile("[a-z-]*\\=(\"[^\"]*\")"), "av");
+ patternColors.put(Pattern.compile("(<!--.*-->)"), "cm");
+ patternColors.put(Pattern.compile("(\\<!\\[CDATA\\[).*"), "cd");
+ patternColors.put(Pattern.compile(".*(]]>)"), "cd");
+ String[] styles = new String[xml.length()];
+ // Match all regexes on this snippet, store positions
+ for (Map.Entry<Pattern, String> entry : patternColors.entrySet()) {
+ Matcher matcher = entry.getKey().matcher(xml);
+ while (matcher.find()) {
+ int s = matcher.start(1);
+ int e = matcher.end();
+ String c = entry.getValue();
+ Arrays.fill(styles, s, e, c);
+ }
+ }
+ AttributedStringBuilder asb = new AttributedStringBuilder();
+ String prev = null;
+ for (int i = 0; i < xml.length(); i++) {
+ String s = styles[i];
+ if (!Objects.equals(s, prev)) {
+ applyStyle(asb, colorMap, s);
+ prev = s;
+ }
+ asb.append(xml.charAt(i));
+ }
+ return asb.toAnsi(terminal);
+ }
+
+ private static void applyStyle(AttributedStringBuilder sb, Map<String, String> colors, String type) {
+ String col = colors.get(type);
+ sb.style(AttributedStyle.DEFAULT);
+ if (col != null && !col.isEmpty()) {
+ sb.appendAnsi("\033[" + col + "m");
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/880b838c/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
index 29c9093..da8643b 100644
--- a/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
+++ b/features/core/src/main/java/org/apache/karaf/features/FeaturesService.java
@@ -170,4 +170,6 @@ public interface FeaturesService {
FeatureState getState(String featureId);
+ String getFeatureXml(Feature feature);
+
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/880b838c/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java b/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
index 3d81425..d9b9272 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/model/Dependency.java
@@ -46,9 +46,9 @@ public class Dependency implements org.apache.karaf.features.Dependency {
@XmlAttribute
protected String version;
@XmlAttribute
- protected boolean prerequisite;
+ protected Boolean prerequisite;
@XmlAttribute
- protected boolean dependency;
+ protected Boolean dependency;
public Dependency() {
// Nothing to do
@@ -115,19 +115,19 @@ public class Dependency implements org.apache.karaf.features.Dependency {
@Override
public boolean isPrerequisite() {
- return prerequisite;
+ return prerequisite == null ? false : prerequisite;
}
- public void setPrerequisite(boolean prerequisite) {
+ public void setPrerequisite(Boolean prerequisite) {
this.prerequisite = prerequisite;
}
@Override
public boolean isDependency() {
- return dependency;
+ return dependency == null ? false : dependency;
}
- public void setDependency(boolean dependency) {
+ public void setDependency(Boolean dependency) {
this.dependency = dependency;
}
http://git-wip-us.apache.org/repos/asf/karaf/blob/880b838c/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
----------------------------------------------------------------------
diff --git a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
index cbb93c3..3e38a6d 100644
--- a/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
+++ b/features/core/src/main/java/org/apache/karaf/features/internal/service/FeaturesServiceImpl.java
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayDeque;
import java.util.ArrayList;
@@ -37,6 +38,7 @@ import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
+import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ExecutionException;
@@ -60,6 +62,8 @@ import org.apache.karaf.features.Repository;
import org.apache.karaf.features.RepositoryEvent;
import org.apache.karaf.features.internal.download.DownloadManager;
import org.apache.karaf.features.internal.download.DownloadManagers;
+import org.apache.karaf.features.internal.model.Features;
+import org.apache.karaf.features.internal.model.JaxbUtil;
import org.apache.karaf.features.internal.region.DigraphHelper;
import org.apache.karaf.features.internal.service.BundleInstallSupport.FrameworkInfo;
import org.apache.karaf.util.ThreadUtils;
@@ -80,6 +84,8 @@ import org.osgi.service.resolver.Resolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.xml.bind.JAXBException;
+
import static java.util.Collections.emptyMap;
import static java.util.stream.Collectors.toSet;
import static org.apache.karaf.features.internal.model.Feature.DEFAULT_VERSION;
@@ -1103,4 +1109,22 @@ public class FeaturesServiceImpl implements FeaturesService, Deployer.DeployCall
private String join(Collection<FeatureReq> reqs) {
return reqs.stream().map(FeatureReq::toString).collect(Collectors.joining(","));
}
+
+ @Override
+ public String getFeatureXml(Feature feature) {
+ try {
+ StringWriter sw = new StringWriter();
+ Features r = new Features();
+ r.getFeature().add((org.apache.karaf.features.internal.model.Feature) feature);
+ JaxbUtil.marshal(r, sw);
+ String[] strs = sw.toString().split("\n");
+ StringJoiner joiner = new StringJoiner("\n");
+ for (int i = 2; i < strs.length - 1; i++) {
+ joiner.add(strs[i]);
+ }
+ return joiner.toString();
+ } catch (JAXBException e) {
+ return null;
+ }
+ }
}