Search in sources :

Example 31 with Features

use of org.apache.karaf.features.internal.model.Features in project karaf by apache.

the class Builder method bootStage.

private Set<Feature> bootStage(Profile bootProfile, Profile startupEffective, FeaturesProcessor processor) throws Exception {
    LOGGER.info("Boot stage");
    // 
    // Handle boot profiles
    // 
    Profile bootOverlay = Profiles.getOverlay(bootProfile, allProfiles, environment);
    Profile bootEffective = Profiles.getEffective(bootOverlay, false);
    // Load startup repositories
    LOGGER.info("   Loading boot repositories");
    Map<String, Features> bootRepositories = loadRepositories(manager, bootEffective.getRepositories(), true, processor);
    // Compute startup feature dependencies
    Set<Feature> allBootFeatures = new HashSet<>();
    for (Features repo : bootRepositories.values()) {
        allBootFeatures.addAll(repo.getFeature());
    }
    // Generate a global feature
    Map<String, Dependency> generatedDep = new HashMap<>();
    Feature generated = new Feature();
    generated.setName(UUID.randomUUID().toString());
    // Add feature dependencies
    for (String nameOrPattern : bootEffective.getFeatures()) {
        // KARAF-5273: feature may be a pattern
        for (String dependency : FeatureSelector.getMatchingFeatures(nameOrPattern, bootRepositories.values())) {
            Dependency dep = generatedDep.get(dependency);
            if (dep == null) {
                dep = createDependency(dependency);
                generated.getFeature().add(dep);
                generatedDep.put(dep.getName(), dep);
            }
            dep.setDependency(false);
        }
    }
    // Add bundles
    for (String location : bootEffective.getBundles()) {
        location = location.replace("profile:", "file:etc/");
        Bundle bun = new Bundle();
        bun.setLocation(location);
        generated.getBundle().add(bun);
    }
    Features rep = new Features();
    rep.setName(UUID.randomUUID().toString());
    rep.getRepository().addAll(bootEffective.getRepositories());
    rep.getFeature().add(generated);
    allBootFeatures.add(generated);
    Downloader downloader = manager.createDownloader();
    // Compute startup feature dependencies
    FeatureSelector selector = new FeatureSelector(allBootFeatures);
    Set<Feature> bootFeatures = selector.getMatching(singletonList(generated.getName()));
    for (Feature feature : bootFeatures) {
        if (feature.isBlacklisted()) {
            LOGGER.info("   Feature " + feature.getId() + " is blacklisted, ignoring");
            continue;
        }
        LOGGER.info("   Feature " + feature.getId() + " is defined as a boot feature");
        // add the feature in the system folder
        Set<BundleInfo> bundleInfos = new HashSet<>();
        for (Bundle bundle : feature.getBundle()) {
            if (!ignoreDependencyFlag || !bundle.isDependency()) {
                bundleInfos.add(bundle);
            }
        }
        for (Conditional cond : feature.getConditional()) {
            if (cond.isBlacklisted()) {
                LOGGER.info("   Conditionial " + cond.getConditionId() + " is blacklisted, ignoring");
            }
            for (Bundle bundle : cond.getBundle()) {
                if (!ignoreDependencyFlag || !bundle.isDependency()) {
                    bundleInfos.add(bundle);
                }
            }
        }
        // Build optional features and known prerequisites
        Map<String, List<String>> prereqs = new HashMap<>();
        prereqs.put("blueprint:", Arrays.asList("deployer", "aries-blueprint"));
        prereqs.put("spring:", Arrays.asList("deployer", "spring"));
        prereqs.put("wrap:", Collections.singletonList("wrap"));
        prereqs.put("war:", Collections.singletonList("war"));
        ArtifactInstaller installer = new ArtifactInstaller(systemDirectory, downloader, blacklist);
        for (BundleInfo bundleInfo : bundleInfos) {
            installer.installArtifact(bundleInfo);
            for (Map.Entry<String, List<String>> entry : prereqs.entrySet()) {
                if (bundleInfo.getLocation().trim().startsWith(entry.getKey())) {
                    for (String prereq : entry.getValue()) {
                        Dependency dep = generatedDep.get(prereq);
                        if (dep == null) {
                            dep = new Dependency();
                            dep.setName(prereq);
                            generated.getFeature().add(dep);
                            generatedDep.put(dep.getName(), dep);
                        }
                        dep.setPrerequisite(true);
                    }
                }
            }
        }
        new ConfigInstaller(etcDirectory, pidsToExtract).installConfigs(feature, downloader, installer);
        // Install libraries
        List<String> libraries = new ArrayList<>();
        for (Library library : feature.getLibraries()) {
            String lib = library.getLocation() + ";type:=" + library.getType() + ";export:=" + library.isExport() + ";delegate:=" + library.isDelegate();
            libraries.add(lib);
        }
        Path configPropertiesPath = etcDirectory.resolve("config.properties");
        Properties configProperties = new Properties(configPropertiesPath.toFile());
        downloadLibraries(downloader, configProperties, libraries, "   ");
        downloader.await();
        // Reformat clauses
        reformatClauses(configProperties, Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
        reformatClauses(configProperties, Constants.FRAMEWORK_BOOTDELEGATION);
        configProperties.save();
    }
    // If there are bundles to install, we can't use the boot features only
    // so keep the generated feature
    Path featuresCfgFile = etcDirectory.resolve("org.apache.karaf.features.cfg");
    if (!generated.getBundle().isEmpty()) {
        File output = etcDirectory.resolve(rep.getName() + ".xml").toFile();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        JaxbUtil.marshal(rep, baos);
        ByteArrayInputStream bais;
        String repoUrl;
        if (karafVersion == KarafVersion.v24) {
            String str = baos.toString();
            str = str.replace("http://karaf.apache.org/xmlns/features/v1.3.0", "http://karaf.apache.org/xmlns/features/v1.2.0");
            str = str.replaceAll(" dependency=\".*?\"", "");
            str = str.replaceAll(" prerequisite=\".*?\"", "");
            for (Feature f : rep.getFeature()) {
                for (Dependency d : f.getFeature()) {
                    if (d.isPrerequisite()) {
                        if (!startupEffective.getFeatures().contains(d.getName())) {
                            LOGGER.warn("Feature " + d.getName() + " is a prerequisite and should be installed as a startup feature.");
                        }
                    }
                }
            }
            bais = new ByteArrayInputStream(str.getBytes());
            repoUrl = "file:etc/" + output.getName();
        } else {
            bais = new ByteArrayInputStream(baos.toByteArray());
            repoUrl = "file:${karaf.home}/etc/" + output.getName();
        }
        Files.copy(bais, output.toPath());
        Properties featuresProperties = new Properties(featuresCfgFile.toFile());
        featuresProperties.put(FEATURES_REPOSITORIES, repoUrl);
        featuresProperties.put(FEATURES_BOOT, generated.getName());
        featuresProperties.save();
    } else {
        String repos = getRepos(rep);
        String boot = getBootFeatures(generatedDep);
        Properties featuresProperties = new Properties(featuresCfgFile.toFile());
        featuresProperties.put(FEATURES_REPOSITORIES, repos);
        featuresProperties.put(FEATURES_BOOT, boot);
        reformatClauses(featuresProperties, FEATURES_REPOSITORIES);
        reformatClauses(featuresProperties, FEATURES_BOOT);
        featuresProperties.save();
    }
    downloader.await();
    return allBootFeatures;
}
Also used : HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) Downloader(org.apache.karaf.features.internal.download.Downloader) Conditional(org.apache.karaf.features.internal.model.Conditional) Properties(org.apache.felix.utils.properties.Properties) Feature(org.apache.karaf.features.internal.model.Feature) Profile(org.apache.karaf.profile.Profile) BundleInfo(org.apache.karaf.features.BundleInfo) Features(org.apache.karaf.features.internal.model.Features) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Path(java.nio.file.Path) Bundle(org.apache.karaf.features.internal.model.Bundle) Dependency(org.apache.karaf.features.internal.model.Dependency) ByteArrayOutputStream(java.io.ByteArrayOutputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) Library(org.apache.karaf.features.Library) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) File(java.io.File)

Example 32 with Features

use of org.apache.karaf.features.internal.model.Features in project karaf by apache.

the class Builder method startupStage.

private Profile startupStage(Profile startupProfile, FeaturesProcessor processor) throws Exception {
    LOGGER.info("Startup stage");
    // 
    // Compute startup
    // 
    Profile startupOverlay = Profiles.getOverlay(startupProfile, allProfiles, environment);
    Profile startupEffective = Profiles.getEffective(startupOverlay, false);
    // Load startup repositories
    LOGGER.info("   Loading startup repositories");
    Map<String, Features> startupRepositories = loadRepositories(manager, startupEffective.getRepositories(), false, processor);
    // 
    // Resolve
    // 
    LOGGER.info("   Resolving startup features and bundles");
    LOGGER.info("      Features: " + startupEffective.getFeatures().stream().collect(Collectors.joining(", ")));
    LOGGER.info("      Bundles: " + startupEffective.getBundles().stream().collect(Collectors.joining(", ")));
    Map<String, Integer> bundles = resolve(manager, resolver, startupRepositories.values(), startupEffective.getFeatures(), startupEffective.getBundles(), startupEffective.getOptionals(), processor);
    // 
    // Generate startup.properties
    // 
    Properties startup = new Properties();
    startup.setHeader(Collections.singletonList("# Bundles to be started on startup, with startlevel"));
    Map<Integer, Set<String>> invertedStartupBundles = MapUtils.invert(bundles);
    for (Map.Entry<Integer, Set<String>> entry : new TreeMap<>(invertedStartupBundles).entrySet()) {
        String startLevel = Integer.toString(entry.getKey());
        for (String location : new TreeSet<>(entry.getValue())) {
            if (useReferenceUrls) {
                if (location.startsWith("mvn:")) {
                    location = "file:" + Parser.pathFromMaven(location);
                }
                if (location.startsWith("file:")) {
                    location = "reference:" + location;
                }
            }
            if (location.startsWith("file:") && karafVersion == KarafVersion.v24) {
                location = location.substring("file:".length());
            }
            startup.put(location, startLevel);
        }
    }
    Path startupProperties = etcDirectory.resolve("startup.properties");
    startup.save(startupProperties.toFile());
    return startupEffective;
}
Also used : Path(java.nio.file.Path) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) Properties(org.apache.felix.utils.properties.Properties) Profile(org.apache.karaf.profile.Profile) TreeSet(java.util.TreeSet) Features(org.apache.karaf.features.internal.model.Features) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TreeMap(java.util.TreeMap)

Example 33 with Features

use of org.apache.karaf.features.internal.model.Features in project karaf by apache.

the class Builder method generateConsistencyReport.

/**
 * Produces human readable XML with <em>feature consistency report</em>.
 * @param repositories
 * @param result
 */
public void generateConsistencyReport(Map<String, Features> repositories, File result, boolean full) {
    Map<String, String> featureId2repository = new HashMap<>();
    // list of feature IDs containing given bundle URIs
    Map<String, Set<String>> bundle2featureId = new TreeMap<>(new URIAwareComparator());
    // map of groupId/artifactId to full URI list to detect "duplicates"
    Map<String, List<String>> ga2uri = new TreeMap<>();
    Set<String> haveDuplicates = new HashSet<>();
    // collect closure of bundles and features
    repositories.forEach((name, features) -> {
        if (full || !features.isBlacklisted()) {
            features.getFeature().forEach(feature -> {
                if (full || !feature.isBlacklisted()) {
                    featureId2repository.put(feature.getId(), name);
                    feature.getBundle().forEach(bundle -> {
                        // normal bundles of feature
                        bundle2featureId.computeIfAbsent(bundle.getLocation().trim(), k -> new TreeSet<>()).add(feature.getId());
                    });
                    feature.getConditional().forEach(cond -> {
                        cond.asFeature().getBundles().forEach(bundle -> {
                            // conditional bundles of feature
                            bundle2featureId.computeIfAbsent(bundle.getLocation().trim(), k -> new TreeSet<>()).add(feature.getId());
                        });
                    });
                }
            });
        }
    });
    // collect bundle URIs - for now, only wrap:mvn: and mvn: are interesting
    bundle2featureId.keySet().forEach(uri -> {
        String originalUri = uri;
        if (uri.startsWith("wrap:mvn:")) {
            uri = uri.substring(5);
            if (uri.indexOf(";") > 0) {
                uri = uri.substring(0, uri.indexOf(";"));
            }
            if (uri.indexOf("$") > 0) {
                uri = uri.substring(0, uri.indexOf("$"));
            }
        }
        if (uri.startsWith("mvn:")) {
            try {
                LocationPattern pattern = new LocationPattern(uri);
                String ga = String.format("%s/%s", pattern.getGroupId(), pattern.getArtifactId());
                ga2uri.computeIfAbsent(ga, k -> new LinkedList<>()).add(originalUri);
            } catch (IllegalArgumentException ignored) {
            /*
                        <!-- hibernate-validator-osgi-karaf-features-5.3.4.Final-features.xml -->
                        <feature name="hibernate-validator-paranamer" version="5.3.4.Final">
                            <feature>hibernate-validator</feature>
                            <bundle>wrap:mvn:com.thoughtworks.paranamer:paranamer:2.8</bundle>
                        </feature>
                     */
            }
        }
    });
    ga2uri.values().forEach(l -> {
        if (l.size() > 1) {
            haveDuplicates.addAll(l);
        }
    });
    if (result == null) {
        return;
    }
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(result))) {
        writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
        writer.write("<?xml-stylesheet type=\"text/xsl\" href=\"bundle-report.xslt\"?>\n");
        writer.write("<consistency-report xmlns=\"urn:apache:karaf:consistency:1.0\">\n");
        writer.write("    <duplicates>\n");
        ga2uri.forEach((key, uris) -> {
            if (uris.size() > 1) {
                try {
                    writer.write(String.format("        <duplicate ga=\"%s\">\n", key));
                    for (String uri : uris) {
                        writer.write(String.format("            <bundle uri=\"%s\">\n", sanitize(uri)));
                        for (String fid : bundle2featureId.get(uri)) {
                            writer.write(String.format("                <feature repository=\"%s\">%s</feature>\n", featureId2repository.get(fid), fid));
                        }
                        writer.write("            </bundle>\n");
                    }
                    writer.write("        </duplicate>\n");
                } catch (IOException e) {
                }
            }
        });
        writer.write("    </duplicates>\n");
        writer.write("    <bundles>\n");
        for (String uri : bundle2featureId.keySet()) {
            writer.write(String.format("        <bundle uri=\"%s\" duplicate=\"%b\">\n", sanitize(uri), haveDuplicates.contains(uri)));
            for (String fid : bundle2featureId.get(uri)) {
                writer.write(String.format("            <feature>%s</feature>\n", fid));
            }
            writer.write("        </bundle>\n");
        }
        writer.write("    </bundles>\n");
        writer.write("</consistency-report>\n");
    } catch (IOException e) {
        throw new RuntimeException(e.getMessage(), e);
    }
}
Also used : Manifest(java.util.jar.Manifest) Dependency(org.apache.karaf.features.internal.model.Dependency) Profile(org.apache.karaf.profile.Profile) Arrays(java.util.Arrays) MultiException(org.apache.karaf.features.internal.util.MultiException) FeaturesProcessorImpl(org.apache.karaf.features.internal.service.FeaturesProcessorImpl) Constants(org.osgi.framework.Constants) FeaturePattern(org.apache.karaf.features.FeaturePattern) KarafPropertiesEditor(org.apache.karaf.tools.utils.KarafPropertiesEditor) LoggerFactory(org.slf4j.LoggerFactory) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) FeaturesService(org.apache.karaf.features.FeaturesService) Collections.singletonList(java.util.Collections.singletonList) Clause(org.apache.felix.utils.manifest.Clause) ByteArrayInputStream(java.io.ByteArrayInputStream) JaxbUtil(org.apache.karaf.features.internal.model.JaxbUtil) Map(java.util.Map) FeaturesProcessing(org.apache.karaf.features.internal.model.processing.FeaturesProcessing) URI(java.net.URI) Repository(org.osgi.service.repository.Repository) Path(java.nio.file.Path) ZipEntry(java.util.zip.ZipEntry) BundleRevision(org.osgi.framework.wiring.BundleRevision) MavenResolver(org.ops4j.pax.url.mvn.MavenResolver) BundleInfo(org.apache.karaf.features.BundleInfo) Blacklist(org.apache.karaf.features.internal.service.Blacklist) Deployer(org.apache.karaf.features.internal.service.Deployer) MapUtils(org.apache.karaf.features.internal.util.MapUtils) Collection(java.util.Collection) Set(java.util.Set) MANIFEST_NAME(java.util.jar.JarFile.MANIFEST_NAME) UUID(java.util.UUID) Library(org.apache.karaf.features.Library) FileSystem(java.nio.file.FileSystem) Attributes(java.util.jar.Attributes) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) ThreadUtils(org.apache.karaf.util.ThreadUtils) List(java.util.List) PropertiesLoader(org.apache.karaf.util.config.PropertiesLoader) Properties(org.apache.felix.utils.properties.Properties) Optional(java.util.Optional) Pattern(java.util.regex.Pattern) DownloadManager(org.apache.karaf.features.internal.download.DownloadManager) Features(org.apache.karaf.features.internal.model.Features) Dictionary(java.util.Dictionary) ZipInputStream(java.util.zip.ZipInputStream) ByteArrayOutputStream(java.io.ByteArrayOutputStream) DownloadCallback(org.apache.karaf.features.internal.download.DownloadCallback) HashMap(java.util.HashMap) ResourceBuilder(org.apache.karaf.features.internal.resolver.ResourceBuilder) Kar(org.apache.karaf.kar.internal.Kar) Function(java.util.function.Function) TreeSet(java.util.TreeSet) StandardCopyOption(java.nio.file.StandardCopyOption) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) StreamProvider(org.apache.karaf.features.internal.download.StreamProvider) ProfileBuilder(org.apache.karaf.profile.ProfileBuilder) Parser(org.apache.karaf.util.maven.Parser) BaseRepository(org.apache.karaf.features.internal.repository.BaseRepository) FeaturesProcessor(org.apache.karaf.features.internal.service.FeaturesProcessor) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) Bundle(org.apache.karaf.features.internal.model.Bundle) MavenResolvers(org.ops4j.pax.url.mvn.MavenResolvers) Downloader(org.apache.karaf.features.internal.download.Downloader) LinkedList(java.util.LinkedList) Hashtable(java.util.Hashtable) LinkedHashSet(java.util.LinkedHashSet) LocationPattern(org.apache.karaf.features.LocationPattern) Logger(org.slf4j.Logger) Profiles(org.apache.karaf.profile.impl.Profiles) MalformedURLException(java.net.MalformedURLException) FileSystemNotFoundException(java.nio.file.FileSystemNotFoundException) Files(java.nio.file.Files) Conditional(org.apache.karaf.features.internal.model.Conditional) BufferedWriter(java.io.BufferedWriter) Resource(org.osgi.resource.Resource) Version(org.apache.karaf.util.Version) FileWriter(java.io.FileWriter) FileOutputStream(java.io.FileOutputStream) IOException(java.io.IOException) ResolverImpl(org.apache.felix.resolver.ResolverImpl) Resolver(org.osgi.service.resolver.Resolver) KarafPropertyEdits(org.apache.karaf.tools.utils.model.KarafPropertyEdits) File(java.io.File) Overrides(org.apache.karaf.features.internal.service.Overrides) TreeMap(java.util.TreeMap) Paths(java.nio.file.Paths) Feature(org.apache.karaf.features.internal.model.Feature) URLUtils(org.ops4j.net.URLUtils) Startup(org.apache.karaf.profile.assembly.Builder.Stage.Startup) Collections(java.util.Collections) FileSystems(java.nio.file.FileSystems) InputStream(java.io.InputStream) Set(java.util.Set) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) FileWriter(java.io.FileWriter) IOException(java.io.IOException) TreeMap(java.util.TreeMap) LinkedList(java.util.LinkedList) BufferedWriter(java.io.BufferedWriter) LocationPattern(org.apache.karaf.features.LocationPattern) TreeSet(java.util.TreeSet) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ArrayList(java.util.ArrayList) LinkedList(java.util.LinkedList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 34 with Features

use of org.apache.karaf.features.internal.model.Features in project karaf by apache.

the class FeatureSelector method getMatchingFeatures.

/**
 * Assuming <code>idOrPattern</code> may be a pattern (with glob and version range), get all matching features
 * @param idOrPattern
 * @param repositories
 * @return
 */
public static Collection<String> getMatchingFeatures(String idOrPattern, Collection<Features> repositories) {
    List<String> result = new LinkedList<>();
    FeaturePattern pattern = new FeaturePattern(idOrPattern);
    for (Features features : repositories) {
        for (Feature feature : features.getFeature()) {
            // blacklisting will be applied anyway, so no need to do it here
            if (/*!feature.isBlacklisted() && */
            pattern.matches(feature.getName(), feature.getVersion())) {
                result.add(feature.getId());
            }
        }
    }
    return result;
}
Also used : FeaturePattern(org.apache.karaf.features.FeaturePattern) Features(org.apache.karaf.features.internal.model.Features) Feature(org.apache.karaf.features.internal.model.Feature) LinkedList(java.util.LinkedList)

Example 35 with Features

use of org.apache.karaf.features.internal.model.Features in project karaf by apache.

the class GenerateDescriptorMojo method writeFeatures.

/*
     * Write all project dependencies as feature
     */
private void writeFeatures(PrintStream out) throws ArtifactResolutionException, ArtifactNotFoundException, IOException, JAXBException, SAXException, ParserConfigurationException, XMLStreamException, MojoExecutionException {
    getLog().info("Generating feature descriptor file " + outputFile.getAbsolutePath());
    // read in an existing feature.xml
    ObjectFactory objectFactory = new ObjectFactory();
    Features features;
    if (inputFile.exists()) {
        filter(inputFile, filteredInputFile);
        features = readFeaturesFile(filteredInputFile);
    } else {
        features = objectFactory.createFeaturesRoot();
    }
    if (features.getName() == null) {
        features.setName(project.getArtifactId());
    }
    Feature feature = null;
    for (Feature test : features.getFeature()) {
        if (test.getName().equals(primaryFeatureName)) {
            feature = test;
        }
    }
    if (feature == null) {
        feature = objectFactory.createFeature();
        feature.setName(primaryFeatureName);
    }
    if (!feature.hasVersion()) {
        feature.setVersion(project.getArtifact().getBaseVersion());
    }
    if (feature.getDescription() == null) {
        feature.setDescription(project.getName());
    }
    if (installMode != null) {
        feature.setInstall(installMode);
    }
    if (project.getDescription() != null && feature.getDetails() == null) {
        feature.setDetails(project.getDescription());
    }
    if (includeProjectArtifact) {
        Bundle bundle = objectFactory.createBundle();
        bundle.setLocation(this.dependencyHelper.artifactToMvn(project.getArtifact(), project.getVersion()));
        if (startLevel != null) {
            bundle.setStartLevel(startLevel);
        }
        feature.getBundle().add(bundle);
    }
    boolean needWrap = false;
    // First pass to look for features
    // Track other features we depend on and their repositories (we track repositories instead of building them from
    // the feature's Maven artifact to allow for multi-feature repositories)
    // TODO Initialise the repositories from the existing feature file if any
    Map<Dependency, Feature> otherFeatures = new HashMap<>();
    Map<Feature, String> featureRepositories = new HashMap<>();
    FeaturesCache cache = new FeaturesCache(featuresCacheSize, artifactCacheSize);
    for (final LocalDependency entry : localDependencies) {
        Object artifact = entry.getArtifact();
        if (excludedArtifactIds.contains(this.dependencyHelper.getArtifactId(artifact))) {
            continue;
        }
        processFeatureArtifact(features, feature, otherFeatures, featureRepositories, cache, artifact, entry.getParent(), true);
    }
    // Do not retain cache beyond this point
    cache = null;
    // Second pass to look for bundles
    if (addBundlesToPrimaryFeature) {
        localDependency: for (final LocalDependency entry : localDependencies) {
            Object artifact = entry.getArtifact();
            if (excludedArtifactIds.contains(this.dependencyHelper.getArtifactId(artifact))) {
                continue;
            }
            if (!this.dependencyHelper.isArtifactAFeature(artifact)) {
                String bundleName = this.dependencyHelper.artifactToMvn(artifact, getVersionOrRange(entry.getParent(), artifact));
                for (ConfigFile cf : feature.getConfigfile()) {
                    if (bundleName.equals(cf.getLocation().replace('\n', ' ').trim())) {
                        // The bundle matches a configfile, ignore it
                        continue localDependency;
                    }
                }
                File bundleFile = this.dependencyHelper.resolve(artifact, getLog());
                Manifest manifest = getManifest(bundleFile);
                if (manifest == null || !ManifestUtils.isBundle(manifest)) {
                    bundleName = "wrap:" + bundleName;
                    needWrap = true;
                }
                Bundle bundle = null;
                for (Bundle b : feature.getBundle()) {
                    if (bundleName.equals(b.getLocation())) {
                        bundle = b;
                        break;
                    }
                }
                if (bundle == null) {
                    bundle = objectFactory.createBundle();
                    bundle.setLocation(bundleName);
                    // Check the features this feature depends on don't already contain the dependency
                    // TODO Perhaps only for transitive dependencies?
                    boolean includedTransitively = simplifyBundleDependencies && isBundleIncludedTransitively(feature, otherFeatures, bundle);
                    if (!includedTransitively && (!"provided".equals(entry.getScope()) || !ignoreScopeProvided)) {
                        feature.getBundle().add(bundle);
                    }
                }
                if ("runtime".equals(entry.getScope())) {
                    bundle.setDependency(true);
                }
                if (startLevel != null && bundle.getStartLevel() == 0) {
                    bundle.setStartLevel(startLevel);
                }
            }
        }
    }
    if (needWrap) {
        Dependency wrapDependency = new Dependency();
        wrapDependency.setName("wrap");
        wrapDependency.setDependency(false);
        wrapDependency.setPrerequisite(true);
        feature.getFeature().add(wrapDependency);
    }
    if ((!feature.getBundle().isEmpty() || !feature.getFeature().isEmpty()) && !features.getFeature().contains(feature)) {
        features.getFeature().add(feature);
    }
    // Add any missing repositories for the included features
    for (Feature includedFeature : features.getFeature()) {
        for (Dependency dependency : includedFeature.getFeature()) {
            Feature dependedFeature = otherFeatures.get(dependency);
            if (dependedFeature != null && !features.getFeature().contains(dependedFeature)) {
                String repository = featureRepositories.get(dependedFeature);
                if (repository != null && !features.getRepository().contains(repository)) {
                    features.getRepository().add(repository);
                }
            }
        }
    }
    JaxbUtil.marshal(features, out);
    try {
        checkChanges(features, objectFactory);
    } catch (Exception e) {
        throw new MojoExecutionException("Features contents have changed", e);
    }
    getLog().info("...done!");
}
Also used : MojoExecutionException(org.apache.maven.plugin.MojoExecutionException) HashMap(java.util.HashMap) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) Bundle(org.apache.karaf.features.internal.model.Bundle) Dependency(org.apache.karaf.features.internal.model.Dependency) LocalDependency(org.apache.karaf.tooling.utils.LocalDependency) Manifest(java.util.jar.Manifest) Feature(org.apache.karaf.features.internal.model.Feature) ProjectBuildingException(org.apache.maven.project.ProjectBuildingException) MavenFilteringException(org.apache.maven.shared.filtering.MavenFilteringException) XMLStreamException(javax.xml.stream.XMLStreamException) ArtifactNotFoundException(org.apache.maven.artifact.resolver.ArtifactNotFoundException) JAXBException(javax.xml.bind.JAXBException) SAXException(org.xml.sax.SAXException) ArtifactResolutionException(org.apache.maven.artifact.resolver.ArtifactResolutionException) IOException(java.io.IOException) MojoExecutionException(org.apache.maven.plugin.MojoExecutionException) MojoFailureException(org.apache.maven.plugin.MojoFailureException) ParserConfigurationException(javax.xml.parsers.ParserConfigurationException) LocalDependency(org.apache.karaf.tooling.utils.LocalDependency) ObjectFactory(org.apache.karaf.features.internal.model.ObjectFactory) Features(org.apache.karaf.features.internal.model.Features) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) File(java.io.File)

Aggregations

Features (org.apache.karaf.features.internal.model.Features)37 Feature (org.apache.karaf.features.internal.model.Feature)21 ArrayList (java.util.ArrayList)14 HashMap (java.util.HashMap)14 File (java.io.File)12 LinkedHashMap (java.util.LinkedHashMap)12 IOException (java.io.IOException)11 LinkedHashSet (java.util.LinkedHashSet)11 URL (java.net.URL)10 HashSet (java.util.HashSet)10 ConfigFile (org.apache.karaf.features.internal.model.ConfigFile)10 Test (org.junit.Test)10 Map (java.util.Map)9 TreeMap (java.util.TreeMap)9 Downloader (org.apache.karaf.features.internal.download.Downloader)8 InputStream (java.io.InputStream)7 List (java.util.List)7 Bundle (org.apache.karaf.features.internal.model.Bundle)7 Conditional (org.apache.karaf.features.internal.model.Conditional)7 Dependency (org.apache.karaf.features.internal.model.Dependency)7