protected void doExecute()

in tooling/karaf-maven-plugin/src/main/java/org/apache/karaf/tooling/VerifyMojo.java [243:422]


    protected void doExecute() throws MojoExecutionException {
        System.setProperty("karaf.home", "target/karaf");
        System.setProperty("karaf.data", "target/karaf/data");

        Hashtable<String, String> properties = new Hashtable<>();

        if (additionalMetadata != null) {
            try (Reader reader = new FileReader(additionalMetadata)) {
                Properties metadata = new Properties();
                metadata.load(reader);
                for (Enumeration<?> e = metadata.propertyNames(); e.hasMoreElements(); ) {
                    Object key = e.nextElement();
                    Object val = metadata.get(key);
                    properties.put(key.toString(), val.toString());
                }
            } catch (IOException e) {
                throw new MojoExecutionException("Unable to load additional metadata from " + additionalMetadata, e);
            }
        }

        Set<String> allDescriptors = new LinkedHashSet<>();
        if (descriptors == null) {
            if (framework == null) {
                framework = Collections.singleton("framework");
            }
            descriptors = new LinkedHashSet<>();
            if (framework.contains("framework")) {
                allDescriptors.add("mvn:org.apache.karaf.features/framework/" + getVersion("org.apache.karaf.features:framework") + "/xml/features");
            }
            String filePrefix = null;
            if (System.getProperty("os.name").contains("Windows")) {
                filePrefix = "file:/";
            } else {
                filePrefix = "file:";
            }
            allDescriptors.add(filePrefix + project.getBuild().getDirectory() + File.separator 
                               + "feature"
                               + File.separator 
                               + "feature.xml");
        } else {
            allDescriptors.addAll(descriptors);
            if (framework != null && framework.contains("framework")) {
                allDescriptors.add("mvn:org.apache.karaf.features/framework/" + getVersion("org.apache.karaf.features:framework") + "/xml/features");
            }
        }

        // TODO: allow using external configuration ?
        ScheduledExecutorService executor = Executors.newScheduledThreadPool(8);
        DownloadManager manager = new CustomDownloadManager(resolver, executor);
        final Map<String, Features> repositories;
        Map<String, List<Feature>> allFeatures = new HashMap<>();
        try {
            repositories = loadRepositories(manager, allDescriptors);
            for (String repoUri : repositories.keySet()) {
                List<Feature> features = repositories.get(repoUri).getFeature();
                // Ack features to inline configuration files urls
                for (Feature feature : features) {
                    for (org.apache.karaf.features.internal.model.Bundle bi : feature.getBundle()) {
                        String loc = bi.getLocation();
                        String nloc = null;
                        if (loc.contains("file:")) {
                            for (ConfigFile cfi : feature.getConfigfile()) {
                                if (cfi.getFinalname().substring(1)
                                        .equals(loc.substring(loc.indexOf("file:") + "file:".length()))) {
                                    nloc = cfi.getLocation();
                                }
                            }
                        }
                        if (nloc != null) {
                            Field field = bi.getClass().getDeclaredField("location");
                            field.setAccessible(true);
                            field.set(bi, loc.substring(0, loc.indexOf("file:")) + nloc);
                        }
                    }
                }
                allFeatures.put(repoUri, features);
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to load features descriptors", e);
        }

        List<Feature> featuresToTest = new ArrayList<>();
        if (verifyTransitive) {
            for (List<Feature> features : allFeatures.values()) {
                featuresToTest.addAll(features);
            }
        } else {
            for (String uri : descriptors) {
                featuresToTest.addAll(allFeatures.get(uri));
            }
        }
        if (features != null && !features.isEmpty()) {
            Pattern pattern = getPattern(features);
            for (Iterator<Feature> iterator = featuresToTest.iterator(); iterator.hasNext();) {
                Feature feature = iterator.next();
                String id = feature.getName() + "/" + feature.getVersion();
                if (!pattern.matcher(id).matches()) {
                    iterator.remove();
                }
            }
        }

        for (String fmk : framework) {
            properties.put("feature.framework." + fmk, fmk);
        }
        Set<String> successes = new LinkedHashSet<>();
        Set<String> ignored = new LinkedHashSet<>();
        Set<String> skipped = new LinkedHashSet<>();
        Map<String, Exception> failures = new LinkedHashMap<>();
        for (Feature feature : featuresToTest) {
            String id = feature.getId();
            if (feature.isBlacklisted()) {
                skipped.add(id);
                getLog().info("Verification of feature " + id + " skipped");
                continue;
            }
            try {
                verifyResolution(new CustomDownloadManager(resolver, executor),
                                 repositories, Collections.singleton(id), properties);
                successes.add(id);
                getLog().info("Verification of feature " + id + " succeeded");
            } catch (Exception e) {
                if (e.getCause() instanceof ResolutionException || !getLog().isDebugEnabled()) {
                    getLog().warn(e.getMessage() + ": " + id);
                    getLog().warn(e.getCause().getMessage());
                } else {
                    getLog().warn(e);
                }
                failures.put(id, e);
                if ("first".equals(fail)) {
                    throw e;
                }
            }
            for (Conditional cond : feature.getConditional()) {
                Set<String> ids = new LinkedHashSet<>();
                ids.add(feature.getId());
                ids.addAll(cond.getCondition());
                String cid = String.join("+", ids);
                try {
                    verifyResolution(manager, repositories, ids, properties);
                    successes.add(cid);
                    getLog().info("Verification of feature " + cid + " succeeded");
                } catch (Exception e) {
                    if (ignoreMissingConditions && e.getCause() instanceof ResolutionException) {
                        boolean ignore = true;
                        Collection<Requirement> requirements = ((ResolutionException) e.getCause()).getUnresolvedRequirements();
                        for (Requirement req : requirements) {
                            ignore &= (IdentityNamespace.IDENTITY_NAMESPACE.equals(req.getNamespace())
                                    && ResourceUtils.TYPE_FEATURE.equals(req.getAttributes().get("type"))
                                    && cond.getCondition().contains(req.getAttributes().get(IdentityNamespace.IDENTITY_NAMESPACE).toString()));
                        }
                        if (ignore) {
                            ignored.add(cid);
                            getLog().warn("Feature resolution failed for " + cid
                                    + "\nMessage: " + e.getCause().getMessage());
                            continue;
                        }
                    }
                    if (e.getCause() instanceof ResolutionException || !getLog().isDebugEnabled()) {
                        getLog().warn(e.getMessage());
                    } else {
                        getLog().warn(e);
                    }
                    failures.put(cid, e);
                    if ("first".equals(fail)) {
                        throw e;
                    }
                }
            }
        }
        executor.shutdown();
        int nb = successes.size() + ignored.size() + failures.size();
        getLog().info("Features verified: " + nb + ", failures: " + failures.size() + ", ignored: " + ignored.size() + ", skipped: " + skipped.size());
        if (!failures.isEmpty()) {
            getLog().info("Failures: " + String.join(", ", failures.keySet()));
        }
        if ("end".equals(fail) && !failures.isEmpty()) {
            throw new MojoExecutionException("Verification failures", new MultiException("Verification failures", new ArrayList<>(failures.values())));
        }
    }