| /* |
| * 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.List; |
| import java.util.Map; |
| |
| import org.apache.felix.gogo.commands.Argument; |
| import org.apache.felix.gogo.commands.Command; |
| import org.apache.felix.gogo.commands.Option; |
| import org.apache.karaf.features.BundleInfo; |
| import org.apache.karaf.features.ConfigFileInfo; |
| import org.apache.karaf.features.Feature; |
| import org.apache.karaf.features.FeaturesService; |
| |
| /** |
| * Utility command to display info about features. |
| */ |
| @Command(scope = "features", name = "info", description = "Shows information about selected feature.") |
| public class InfoFeatureCommand extends FeaturesCommandSupport { |
| |
| @Argument(index = 0, name = "name", description = "The name of the feature", required = true, multiValued = false) |
| 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 = "-t", aliases={"--tree"}, description="Display feature tree", required = false, multiValued = false) |
| private boolean tree; |
| |
| protected void doExecute(FeaturesService admin) throws Exception { |
| Feature feature = null; |
| |
| if (version != null && version.length() > 0) { |
| feature = admin.getFeature(name, version); |
| } else { |
| feature = admin.getFeature(name); |
| } |
| |
| if (feature == null) { |
| System.out.println("Feature not found"); |
| return; |
| } |
| |
| // default behavior |
| if (!config && !dependency && !bundle) { |
| config = true; |
| dependency = true; |
| bundle = true; |
| } |
| |
| System.out.println("Description of " + feature.getName() + " " + feature.getVersion() + " feature"); |
| System.out.println("----------------------------------------------------------------"); |
| if(feature.getDetails() != null && feature.getDetails().length() >0) { |
| System.out.print(feature.getDetails()); |
| System.out.println("----------------------------------------------------------------"); |
| } |
| if (config) { |
| displayConfigInformation(feature); |
| displayConfigFileInformation(feature); |
| } |
| |
| if (dependency) { |
| displayDependencyInformation(feature); |
| } |
| |
| if (bundle) { |
| displayBundleInformation(feature); |
| } |
| |
| if (tree) { |
| if (config || dependency || bundle) { |
| System.out.println("\nFeature tree"); |
| } |
| |
| int unresolved = displayFeatureTree(admin, feature, 0, false); |
| if (unresolved > 0) { |
| System.out.println("Tree contains " + unresolved + " unresolved dependencies"); |
| System.out.println(" * means that node declares dependency but the dependant feature is not available."); |
| } |
| } |
| } |
| |
| private void displayBundleInformation(Feature feature) { |
| List<BundleInfo> bundleInfos = feature.getBundles(); |
| if (bundleInfos.isEmpty()) { |
| System.out.println("Feature has no bundles."); |
| } else { |
| System.out.println("Feature contains followed bundles:"); |
| for (BundleInfo featureBundle : bundleInfos) { |
| int startLevel = featureBundle.getStartLevel(); |
| StringBuilder sb = new StringBuilder(); |
| sb.append(" ").append(featureBundle.getLocation()); |
| if(startLevel > 0) { |
| sb.append(" start-level=").append(startLevel); |
| } |
| System.out.println(sb.toString()); |
| } |
| } |
| } |
| |
| private void displayDependencyInformation(Feature feature) { |
| List<Feature> dependencies = feature.getDependencies(); |
| if (dependencies.isEmpty()) { |
| System.out.println("Feature has no dependencies."); |
| } else { |
| System.out.println("Feature depends on:"); |
| for (Feature featureDependency : dependencies) { |
| System.out.println(" " + featureDependency.getName() + " " + featureDependency.getVersion()); |
| } |
| } |
| } |
| |
| private void displayConfigInformation(Feature feature) { |
| Map<String, Map<String, String>> configurations = feature.getConfigurations(); |
| if (configurations.isEmpty()) { |
| System.out.println("Feature has no configuration"); |
| } else { |
| System.out.println("Feature configuration:"); |
| for (String name : configurations.keySet()) { |
| System.out.println(" " + name); |
| } |
| } |
| } |
| |
| private void displayConfigFileInformation(Feature feature) { |
| List<ConfigFileInfo> configurationFiles = feature.getConfigurationFiles(); |
| if (configurationFiles.isEmpty()) { |
| System.out.println("Feature has no configuration files"); |
| } else { |
| System.out.println("Feature configuration files: "); |
| for (ConfigFileInfo configFileInfo : configurationFiles) { |
| System.out.println(" " + configFileInfo.getFinalname()); |
| } |
| } |
| } |
| |
| |
| private int displayFeatureTree(FeaturesService admin, Feature feature, int level, boolean last) throws Exception { |
| int unresolved = 0; |
| String prefix = repeat(" ", level); |
| |
| Feature resolved = resolveFeature(admin, feature); |
| if (resolved != null) { |
| System.out.println(prefix + " " + resolved.getName() + " " + resolved.getVersion()); |
| } else { |
| System.out.println(prefix + " " + feature.getName() + " " + feature.getVersion() + " *"); |
| unresolved++; |
| } |
| |
| if (bundle) { |
| List<BundleInfo> bundles = resolved != null ? resolved.getBundles() : feature.getBundles(); |
| for (int i = 0, j = bundles.size(); i < j; i++) { |
| System.out.println(prefix + " " + (i+1 == j ? "\\" : "+") + " " + bundles.get(i).getLocation()); |
| } |
| } |
| List<Feature> dependencies = resolved != null ? resolved.getDependencies() : feature.getDependencies(); |
| for (int i = 0, j = dependencies.size(); i < j; i++) { |
| Feature toDisplay = resolveFeature(admin, dependencies.get(i)); |
| if (toDisplay == null) { |
| toDisplay = dependencies.get(i); |
| } |
| unresolved += displayFeatureTree(admin, toDisplay, level+1, i + 1 == j); |
| } |
| |
| return unresolved; |
| } |
| |
| private Feature resolveFeature(FeaturesService admin, Feature feature) throws Exception { |
| return admin.getFeature(feature.getName(), feature.getVersion()); |
| } |
| |
| private static String repeat(String string, int times) { |
| if (times <= 0) { |
| return ""; |
| } |
| else if (times % 2 == 0) { |
| return repeat(string+string, times/2); |
| } |
| else { |
| return string + repeat(string+string, times/2); |
| } |
| } |
| } |