| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.karaf.features.command; |
| |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import org.apache.karaf.features.BundleInfo; |
| import org.apache.karaf.features.Conditional; |
| import org.apache.karaf.features.ConfigFileInfo; |
| import org.apache.karaf.features.ConfigInfo; |
| import org.apache.karaf.features.Dependency; |
| import org.apache.karaf.features.Feature; |
| import org.apache.karaf.features.FeaturesService; |
| import org.apache.karaf.features.command.completers.AllFeatureCompleter; |
| 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.Service; |
| |
| @Command(scope = "feature", name = "info", description = "Shows information about selected feature.") |
| @Service |
| public class InfoFeatureCommand extends FeaturesCommandSupport { |
| |
| private static final String INDENT = " "; |
| private static final String FEATURE_CONTENT = "Feature"; |
| private static final String CONDITIONAL_CONTENT = "Conditional(%s)"; |
| |
| @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false) |
| @Completion(AllFeatureCompleter.class) |
| private String name; |
| |
| @Argument(index = 1, name = "version", description = "The version of the feature", required = false, multiValued = false) |
| private String version; |
| |
| @Option(name = "-c", aliases={"--configuration"}, description="Display configuration info", required = false, multiValued = false) |
| private boolean config; |
| |
| @Option(name = "-d", aliases={"--dependency"}, description="Display dependencies info", required = false, multiValued = false) |
| private boolean dependency; |
| |
| @Option(name = "-b", aliases={"--bundle"}, description="Display bundles info", required = false, multiValued = false) |
| private boolean bundle; |
| |
| @Option(name = "--conditional", description="Display conditional info", required = false, multiValued = false) |
| private boolean conditional; |
| |
| @Option(name = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false) |
| private boolean tree; |
| |
| protected void doExecute(FeaturesService admin) throws Exception { |
| Feature[] features = null; |
| |
| if (version != null && version.length() > 0) { |
| features = admin.getFeatures(name, version); |
| } else { |
| features = admin.getFeatures(name); |
| } |
| |
| if (features == null || features.length == 0) { |
| System.out.println("Feature not found"); |
| return; |
| } |
| |
| // default behavior |
| if (!config && !dependency && !bundle && !conditional) { |
| config = true; |
| dependency = true; |
| bundle = true; |
| conditional = true; |
| } |
| |
| boolean first = true; |
| for (Feature feature : features) { |
| if (first) { |
| first = false; |
| } else { |
| System.out.println("------------------------------------"); |
| } |
| System.out.println("Feature " + feature.getName() + " " + feature.getVersion()); |
| if (feature.getDescription() != null) { |
| System.out.println("Description:"); |
| System.out.println(INDENT + feature.getDescription()); |
| } |
| |
| if (feature.getDetails() != null) { |
| System.out.println("Details:"); |
| printWithIndent(feature.getDetails()); |
| } |
| |
| if (config) { |
| displayConfigInformation(feature, FEATURE_CONTENT); |
| displayConfigFileInformation(feature, FEATURE_CONTENT); |
| } |
| |
| if (dependency) { |
| displayDependencyInformation(feature, FEATURE_CONTENT); |
| } |
| |
| if (bundle) { |
| displayBundleInformation(feature, FEATURE_CONTENT); |
| } |
| |
| if (conditional) { |
| displayConditionalInfo(feature); |
| } |
| |
| if (tree) { |
| if (config || dependency || bundle) { |
| System.out.println("\nFeature tree"); |
| } |
| |
| int unresolved = displayFeatureTree(admin, feature.getName(), feature.getVersion(), ""); |
| if (unresolved > 0) { |
| System.out.println("Tree contains " + unresolved + " unresolved dependencies"); |
| System.out.println(" * means that node declares dependency but the dependent feature is not available."); |
| } |
| } |
| } |
| } |
| |
| private void printWithIndent(String details) { |
| String[] lines = details.split("\r?\n"); |
| for (String line : lines) { |
| System.out.println(INDENT + line); |
| } |
| } |
| |
| private void displayBundleInformation(Feature feature, String contentType) { |
| List<BundleInfo> bundleInfos = feature.getBundles(); |
| if (bundleInfos.isEmpty()) { |
| System.out.println(contentType + " has no bundles."); |
| } else { |
| System.out.println(contentType + " contains followed bundles:"); |
| for (BundleInfo featureBundle : bundleInfos) { |
| int startLevel = featureBundle.getStartLevel(); |
| StringBuilder sb = new StringBuilder(); |
| sb.append(INDENT).append(featureBundle.getLocation()); |
| if(startLevel > 0) { |
| sb.append(" start-level=").append(startLevel); |
| } |
| System.out.println(sb.toString()); |
| } |
| } |
| } |
| |
| private void displayDependencyInformation(Feature feature, String contentType) { |
| List<Dependency> dependencies = feature.getDependencies(); |
| if (dependencies.isEmpty()) { |
| System.out.println(contentType + " has no dependencies."); |
| } else { |
| System.out.println(contentType + " depends on:"); |
| for (Dependency featureDependency : dependencies) { |
| System.out.println(INDENT + featureDependency.getName() + " " + featureDependency.getVersion()); |
| } |
| } |
| } |
| |
| private void displayConfigInformation(Feature feature, String contentType) { |
| List<ConfigInfo> configurations = feature.getConfigurations(); |
| if (configurations.isEmpty()) { |
| System.out.println(contentType + " has no configuration"); |
| } else { |
| System.out.println(contentType + " configuration:"); |
| for (ConfigInfo configInfo : configurations) { |
| System.out.println(INDENT + configInfo.getName()); |
| } |
| } |
| } |
| |
| private void displayConfigFileInformation(Feature feature, String contentType) { |
| List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles(); |
| if (configurationFiles.isEmpty()) { |
| System.out.println(contentType + " has no configuration files"); |
| } else { |
| System.out.println(contentType + " configuration files: "); |
| for (ConfigFileInfo configFileInfo : configurationFiles) { |
| System.out.println(INDENT + configFileInfo.getFinalname()); |
| } |
| } |
| } |
| |
| /** |
| * Called originally with featureName and featureVersion that have already been resolved successfully. |
| * |
| * @param admin |
| * @param featureName |
| * @param featureVersion |
| * @param prefix |
| * @return |
| * @throws Exception |
| */ |
| private int displayFeatureTree(FeaturesService admin, String featureName, String featureVersion, String prefix) throws Exception { |
| int unresolved = 0; |
| |
| Feature[] resolvedFeatures = admin.getFeatures(featureName, featureVersion); |
| for (Feature resolved:resolvedFeatures) { |
| if (resolved != null) { |
| System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion()); |
| } else { |
| System.out.println(prefix + " " + featureName + " " + featureVersion + " *"); |
| unresolved++; |
| } |
| |
| if (resolved != null) { |
| if (bundle) { |
| List<String> bundleLocation = new LinkedList<String>(); |
| List<BundleInfo> bundles = resolved.getBundles(); |
| for (BundleInfo bundleInfo : bundles) { |
| bundleLocation.add(bundleInfo.getLocation()); |
| } |
| |
| if (conditional) { |
| for (Conditional cond : resolved.getConditional()) { |
| List<String> condition = cond.getCondition(); |
| List<BundleInfo> conditionalBundles = cond.getBundles(); |
| for (BundleInfo bundleInfo : conditionalBundles) { |
| bundleLocation.add(bundleInfo.getLocation() + "(condition:" + condition + ")"); |
| } |
| } |
| } |
| for (int i = 0, j = bundleLocation.size(); i < j; i++) { |
| System.out.println(prefix + " " + (i + 1 == j ? "\\" : "+") + " " + bundleLocation.get(i)); |
| } |
| } |
| prefix += " "; |
| List<Dependency> dependencies = resolved.getDependencies(); |
| for (int i = 0, j = dependencies.size(); i < j; i++) { |
| Dependency toDisplay = dependencies.get(i); |
| unresolved += displayFeatureTree(admin, toDisplay.getName(), toDisplay.getVersion(), prefix + 1); |
| } |
| |
| if (conditional) { |
| for (Conditional cond : resolved.getConditional()) { |
| 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); |
| } |
| } |
| } |
| } |
| } |
| |
| return unresolved; |
| } |
| |
| private void displayConditionalInfo(Feature feature) { |
| List<? extends Conditional> conditionals = feature.getConditional(); |
| if (conditionals.isEmpty()) { |
| System.out.println("Feature has no conditionals."); |
| } else { |
| System.out.println("Feature contains followed conditionals:"); |
| for (Conditional featureConditional : conditionals) { |
| String conditionDescription = getConditionDescription(featureConditional); |
| Feature wrappedConditional = featureConditional.asFeature(); |
| if (config) { |
| displayConfigInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription)); |
| displayConfigFileInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription)); |
| } |
| |
| if (dependency) { |
| displayDependencyInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription)); |
| } |
| |
| if (bundle) { |
| displayBundleInformation(wrappedConditional, String.format(CONDITIONAL_CONTENT, conditionDescription)); |
| } |
| } |
| } |
| } |
| |
| private String getConditionDescription(Conditional cond) { |
| StringBuffer sb = new StringBuffer(); |
| for (String dep : cond.getCondition()) { |
| if (sb.length() > 0) { |
| sb.append(" "); |
| } |
| sb.append(dep); |
| } |
| return sb.toString(); |
| } |
| |
| } |