public void waitForFeature(String featureName, Predicate<FeatureState> predicate) throws Exception { boolean ready = false; long timeoutLimit = System.currentTimeMillis() + REQUIRED_BUNDLES_TIMEOUT; while (!ready) { FeaturesService featuresService = getFeaturesService(); if (featuresService != null) { Feature feature = featuresService.getFeature(featureName); FeatureState state = featuresService.getState(feature.getName() + "/" + feature.getVersion()); if (state == null) { LOGGER.warn("No Feature found for featureName: {}", featureName); return; } else if (predicate.test(state)) { ready = true; } } if (!ready) { if (System.currentTimeMillis() > timeoutLimit) { printInactiveBundles(); fail( String.format( "Feature did not change to State [" + predicate.toString() + "] within %d minutes.", TimeUnit.MILLISECONDS.toMinutes(REQUIRED_BUNDLES_TIMEOUT))); } LOGGER.info("Feature [{}] not [{}], sleeping...", featureName, predicate.toString()); Thread.sleep(1000); } } }
@Override public boolean matches(DependencyTree dependencyTree) { boolean result = false; if (!getDependencyTreeFilter().matches(dependencyTree)) { try { Feature feature = Features.getFeatureForBundle(service.listFeatures(), dependencyTree); if (feature != null) { String replacement = String.format("%s/%s", feature.getName(), feature.getVersion()); features.add(replacement); LOG.info( String.format( "Installing feature %s for maven dependency %s/%s/%s", replacement, dependencyTree.getGroupId(), dependencyTree.getArtifactId(), dependencyTree.getVersion())); result = true; } } catch (Exception e) { LOG.debug( String.format( "Unable to retrieve features information while processing dependency %s", dependencyTree.getArtifactId()), e); } } return result; }
/* * Get a list of bundle locations in a feature */ private List<String> getBundleLocations(Feature feature) { List<String> result = new LinkedList<String>(); if (feature != null && feature.getBundles() != null) { for (BundleInfo bundle : feature.getBundles()) { result.add(bundle.getLocation()); } } return result; }
/* * Validate if all features in a repository have bundles which can be resolved */ private void validateImportsExports(Repository repository) throws ArtifactResolutionException, ArtifactNotFoundException, Exception { for (Feature feature : repository.getFeatures()) { // make sure the feature hasn't been validated before as a dependency if (!featureExports.containsKey(feature.getName())) { validateImportsExports(feature); } } }
public Feature get(String name, String version) throws Exception { for (Feature feature : features) { if (name.equals(feature.getName()) && version.equals(feature.getVersion())) { return feature; } } throw new Exception( String.format("Unable to find definition for feature %s (version %s)", name, version)); }
public void assertFeatureInstalled(String featureName) { Feature[] features = featuresService.listInstalledFeatures(); for (Feature feature : features) { if (featureName.equals(feature.getName())) { return; } } fail("Feature " + featureName + " should be installed but is not"); }
@Override public Set<BundleInfo> getBundles() throws ApplicationServiceException { Set<BundleInfo> bundles = new TreeSet<BundleInfo>(new BundleInfoComparator()); for (Feature curFeature : getFeatures()) { bundles.addAll(curFeature.getBundles()); } return bundles; }
/* * Analyze exports in all features in the repository without validating the features * (e.g. used for <repository> elements found in a descriptor) */ private void analyzeExports(Repository repository) throws Exception { for (Feature feature : repository.getFeatures()) { Set<Clause> exports = new HashSet<Clause>(); for (String bundle : getBundleLocations(feature)) { exports.addAll(getExports(getManifest(bundle, bundles.get(bundle)))); } info(" scanning feature %s for exports", feature.getName()); featureExports.put(feature.getName(), exports); } }
boolean featureUninstall(Feature feature) { String name = feature.getName(); String version = feature.getVersion(); try { featuresService.uninstallFeature(name, version); return true; } catch (Exception e) { logger.error("Unable to uninstall feature: " + name, e); return false; } }
boolean featureInstall(Feature feature) { String name = feature.getName(); String version = feature.getVersion(); EnumSet<Option> options = EnumSet.of(Option.Verbose); try { featuresService.installFeature(name, version, options); return true; } catch (Exception e) { logger.error("Unable to uninstall feature: " + name, e); return false; } }
/* * Validate if all imports for a feature are being matched with exports */ private void validateImportsExports(Feature feature) throws Exception { Map<Clause, String> imports = new HashMap<Clause, String>(); Set<Clause> exports = new HashSet<Clause>(); for (Dependency dependency : feature.getDependencies()) { if (featureExports.containsKey(dependency.getName())) { exports.addAll(featureExports.get(dependency.getName())); } else { validateImportsExports(features.get(dependency.getName(), dependency.getVersion())); } } for (String bundle : getBundleLocations(feature)) { Manifest meta = manifests.get(bundles.get(bundle)); exports.addAll(getExports(meta)); for (Clause clause : getMandatoryImports(meta)) { imports.put(clause, bundle); } } // setting up the set of required imports Set<Clause> requirements = new HashSet<Clause>(); requirements.addAll(imports.keySet()); // now, let's remove requirements whenever we find a matching export for them for (Clause element : imports.keySet()) { if (systemExports.contains(element.getName())) { debug("%s is resolved by a system bundle export or provided bundle", element); requirements.remove(element); continue; } for (Clause export : exports) { if (matches(element, export)) { debug("%s is resolved by export %s", element, export); requirements.remove(element); continue; } debug("%s is not resolved by export %s", element, export); } } // if there are any more requirements left here, there's a problem with the feature if (!requirements.isEmpty()) { warn("Failed to validate feature %s", feature.getName()); for (Clause entry : requirements) { warn("No export found to match %s (imported by %s)", entry, imports.get(entry)); } throw new Exception( String.format( "%d unresolved imports in feature %s", requirements.size(), feature.getName())); } info(" OK: imports resolved for %s", feature.getName()); featureExports.put(feature.getName(), exports); }
private Set<String> getFeatureLocations() throws Exception { Set<String> bundleLocations = new LinkedHashSet<String>(); for (Feature feature : featuresService.listFeatures()) { try { for (BundleInfo info : feature.getBundles()) { bundleLocations.add(info.getLocation()); } } catch (Exception e) { // Ignore } } return bundleLocations; }
@Override public Set<String> listCapabilities() { Set<String> ids = new HashSet<>(); try { for (Feature feature : featuresService.listFeatures()) { ids.add(feature.getName()); } } catch (Exception e) { logger.error("Unknown error trying to retrieve available Karaf features", e); return ids; } return ids; }
@Override public Set<ICapability> getAllCapabilities() { Set<ICapability> capabilities = new HashSet<ICapability>(); try { for (Feature feature : featuresService.listFeatures()) { ICapability capabilityById = this.getCapabilityById(feature.getName()); if (capabilityById != null) { capabilities.add(capabilityById); } } } catch (Exception e) { logger.error("Unknown error trying to retrieve available Karaf features", e); return capabilities; } return capabilities; }
/** * Get the list of features where the bundle is belonging. * * @param bundleLocation the bundle location. * @return the list of feature where the bundle is present. * @throws Exception in case of retrieval failure. */ protected List<Feature> retrieveFeature(String bundleLocation) throws Exception { Feature[] features = featuresService.listFeatures(); List<Feature> matchingFeatures = new ArrayList<Feature>(); for (Feature feature : features) { List<BundleInfo> bundles = feature.getBundles(); for (BundleInfo bundleInfo : bundles) { String location = bundleInfo.getLocation(); if (location.equalsIgnoreCase(bundleLocation)) { matchingFeatures.add(feature); LOGGER.debug( "CELLAR BUNDLE: found a feature {} containing bundle {}", feature.getName(), bundleLocation); } } } return matchingFeatures; }
@Override public List<Map<String, Object>> getInstallationProfiles() { List<Feature> installationProfiles = appService.getInstallationProfiles(); List<Map<String, Object>> profiles = new ArrayList<Map<String, Object>>(); for (Feature profile : installationProfiles) { Map<String, Object> profileMap = new HashMap<String, Object>(); profileMap.put(INSTALL_PROFILE_NAME, profile.getName()); profileMap.put(INSTALL_PROFILE_DESCRIPTION, profile.getDescription()); List<String> includedFeatures = new ArrayList<>(); profile.getDependencies().forEach(dep -> includedFeatures.add(dep.getName())); profileMap.put(INSTALL_PROFILE_DEFAULT_APPLICATIONS, includedFeatures); profiles.add(profileMap); } return profiles; }
/** * Check if a feature is already installed locally. * * @param name the feature name. * @param version the feature version. * @return true if the feature is already installed locally, false else. */ public Boolean isFeatureInstalledLocally(String name, String version) { if (featuresService != null) { try { Feature[] localFeatures = featuresService.listInstalledFeatures(); if (localFeatures != null && localFeatures.length > 0) { for (Feature localFeature : localFeatures) { if (localFeature.getName().equals(name) && (localFeature.getVersion().equals(version) || version == null)) return true; } } } catch (Exception e) { LOGGER.warn( "CELLAR FEATURES: can't check if the feature {}/{} is installed locally", name, version, e); } } return false; }
private void installPackage(final Map<String, Object> config) { Object packageName = config.get("package"); String name = PREFIX + PREFIX_PACKAGE + ((String) packageName).trim(); installFeature(name); // uninstall all other packages try { for (Feature feature : featuresService.listFeatures()) { if (feature.getName().startsWith(PREFIX + PREFIX_PACKAGE) && !feature.getName().equals(name) && featuresService.isInstalled(feature)) { try { featuresService.uninstallFeature(feature.getName()); } catch (Exception e) { logger.error("Failed uninstalling '{}': {}", feature.getName(), e.getMessage()); } } } } catch (Exception e) { logger.error("Failed retrieving features: {}", e.getMessage()); } }
/** * Creates a new instance of application. * * @param repo Creates the application from a Karaf Feature Repository object. */ public ApplicationImpl(Repository repo) { location = repo.getURI(); try { String[] parts = repo.getName().split("-[0-9]"); if (parts.length != 0) { name = parts[0]; version = repo.getName().substring(name.length() + 1); } else { name = repo.getName(); version = "0.0.0"; } features = new HashSet<>(Arrays.asList(repo.getFeatures())); } catch (Exception e) { logger.warn( "Error occured while trying to parse information for application. Application created but may have missing information."); features = new HashSet<>(); } autoInstallFeatures = new HashSet<>(); if (features.size() == 1) { autoInstallFeatures.add(features.iterator().next()); } else { autoInstallFeatures.addAll( features .stream() .filter( curFeature -> StringUtils.equalsIgnoreCase( Feature.DEFAULT_INSTALL_MODE, curFeature.getInstall())) .collect(Collectors.toList())); } // Determine mainFeature if (autoInstallFeatures.size() == 1) { mainFeature = autoInstallFeatures.iterator().next(); name = mainFeature.getName(); version = mainFeature.getVersion(); description = mainFeature.getDescription(); } else { Optional<Feature> first = autoInstallFeatures.stream().filter(f -> name.equals(f.getName())).findFirst(); if (first.isPresent()) { mainFeature = first.get(); name = mainFeature.getName(); version = mainFeature.getVersion(); description = mainFeature.getDescription(); } } if (mainFeature == null) { logger.debug( "Could not determine main feature in {}, using defaults. Each application " + "should have 1 feature with the same name as the repository or 1 auto" + " install feature. This Application will take no action when started" + " or stopped.", name); } }
public String getInstall() { return feature.getInstall(); }
public void watchForUnInstall(Feature feature, SettableFuture<Boolean> uninstallFuture) { futures.put(feature.getId(), new InstallFuture(uninstallFuture, UNINSTALL)); }
boolean isAutoInstall(Feature feature) { return feature.getInstall() != null && feature.getInstall().equals(Feature.DEFAULT_INSTALL_MODE); }