Search in sources :

Example 1 with MultiException

use of org.apache.karaf.features.internal.util.MultiException in project karaf by apache.

the class Deployer method deploy.

/**
     * Perform a deployment.
     *
     * @param dstate  deployment state
     * @param request deployment request
     * @throws Exception in case of deployment failure.
     */
public void deploy(DeploymentState dstate, DeploymentRequest request) throws Exception {
    boolean noRefreshUnmanaged = request.options.contains(FeaturesService.Option.NoAutoRefreshUnmanagedBundles);
    boolean noRefreshManaged = request.options.contains(FeaturesService.Option.NoAutoRefreshManagedBundles);
    boolean noRefresh = request.options.contains(FeaturesService.Option.NoAutoRefreshBundles);
    boolean noStart = request.options.contains(FeaturesService.Option.NoAutoStartBundles);
    boolean verbose = request.options.contains(FeaturesService.Option.Verbose);
    boolean simulate = request.options.contains(FeaturesService.Option.Simulate);
    boolean noManageBundles = request.options.contains(FeaturesService.Option.NoAutoManageBundles);
    boolean showWiring = request.options.contains(FeaturesService.Option.DisplayFeaturesWiring) || request.options.contains(FeaturesService.Option.DisplayAllWiring);
    boolean showFeaturesWiringOnly = request.options.contains(FeaturesService.Option.DisplayFeaturesWiring) && !request.options.contains(FeaturesService.Option.DisplayAllWiring);
    // TODO: add an option to unmanage bundles instead of uninstalling those
    Map<String, Set<Long>> managedBundles = copy(dstate.state.managedBundles);
    Map<String, Set<Bundle>> unmanagedBundles = apply(diff(dstate.bundlesPerRegion, dstate.state.managedBundles), map(dstate.bundles));
    // Resolve
    SubsystemResolver resolver = new SubsystemResolver(this.resolver, manager);
    resolver.prepare(dstate.features.values(), request.requirements, apply(unmanagedBundles, adapt(BundleRevision.class)));
    Set<String> prereqs = resolver.collectPrerequisites();
    if (!prereqs.isEmpty()) {
        for (Iterator<String> iterator = prereqs.iterator(); iterator.hasNext(); ) {
            String prereq = iterator.next();
            String[] parts = prereq.split("/");
            String name = parts[0];
            String version = parts[1];
            VersionRange range = getRange(version, request.featureResolutionRange);
            boolean found = false;
            for (Set<String> featureSet : dstate.state.installedFeatures.values()) {
                for (String feature : featureSet) {
                    String[] p = feature.split("/");
                    found = name.equals(p[0]) && range.contains(VersionTable.getVersion(p[1]));
                    if (found) {
                        break;
                    }
                }
                if (found) {
                    break;
                }
            }
            if (found) {
                iterator.remove();
            }
        }
    }
    if (!prereqs.isEmpty()) {
        if (request.requirements.get(ROOT_REGION).containsAll(prereqs)) {
            throw new CircularPrerequisiteException(prereqs);
        }
        DeploymentRequest newRequest = new DeploymentRequest();
        newRequest.bundleUpdateRange = request.bundleUpdateRange;
        newRequest.featureResolutionRange = request.featureResolutionRange;
        newRequest.serviceRequirements = request.serviceRequirements;
        newRequest.globalRepository = request.globalRepository;
        newRequest.options = request.options;
        newRequest.overrides = request.overrides;
        newRequest.requirements = copy(dstate.state.requirements);
        for (String prereq : prereqs) {
            addToMapSet(newRequest.requirements, ROOT_REGION, prereq);
        }
        newRequest.stateChanges = Collections.emptyMap();
        newRequest.updateSnaphots = request.updateSnaphots;
        deploy(dstate, newRequest);
        throw new PartialDeploymentException(prereqs);
    }
    resolver.resolve(request.overrides, request.featureResolutionRange, request.serviceRequirements, request.globalRepository, request.outputFile);
    Map<String, StreamProvider> providers = resolver.getProviders();
    Map<String, Set<Resource>> featuresPerRegion = resolver.getFeaturesPerRegions();
    Map<String, Set<String>> installedFeatures = apply(featuresPerRegion, featureId());
    Map<String, Set<String>> newFeatures = diff(installedFeatures, dstate.state.installedFeatures);
    Map<String, Set<String>> delFeatures = diff(dstate.state.installedFeatures, installedFeatures);
    //
    // Compute requested features state
    //
    Map<String, Map<String, String>> stateFeatures = copy(dstate.state.stateFeatures);
    for (Map.Entry<String, Set<String>> entry : delFeatures.entrySet()) {
        Map<String, String> map = stateFeatures.get(entry.getKey());
        if (map != null) {
            map.keySet().removeAll(entry.getValue());
            if (map.isEmpty()) {
                stateFeatures.remove(entry.getKey());
            }
        }
    }
    for (Map.Entry<String, Map<String, FeatureState>> entry1 : request.stateChanges.entrySet()) {
        String region = entry1.getKey();
        Map<String, String> regionStates = stateFeatures.get(region);
        if (regionStates != null) {
            for (Map.Entry<String, FeatureState> entry2 : entry1.getValue().entrySet()) {
                String feature = entry2.getKey();
                if (regionStates.containsKey(feature)) {
                    regionStates.put(feature, entry2.getValue().name());
                }
            }
        }
    }
    for (Map.Entry<String, Set<String>> entry : newFeatures.entrySet()) {
        for (String feature : entry.getValue()) {
            Map<String, String> map = stateFeatures.computeIfAbsent(entry.getKey(), k -> new HashMap<>());
            map.put(feature, noStart ? FeatureState.Installed.name() : FeatureState.Started.name());
        }
    }
    // Compute information for each bundle
    Map<String, Map<String, BundleInfo>> bundleInfos = resolver.getBundleInfos();
    //
    // Compute deployment
    //
    Deployer.Deployment deployment = computeDeployment(dstate, request, resolver);
    //
    // Compute the set of bundles to refresh
    //
    // sort is only used for display
    Map<Bundle, String> toRefresh = new TreeMap<>(new BundleComparator());
    for (Deployer.RegionDeployment regionDeployment : deployment.regions.values()) {
        for (Bundle b : regionDeployment.toDelete) {
            toRefresh.put(b, "Bundle will be uninstalled");
        }
        for (Bundle b : regionDeployment.toUpdate.keySet()) {
            toRefresh.put(b, "Bundle will be updated");
        }
    }
    if (!noRefreshManaged) {
        computeBundlesToRefresh(toRefresh, dstate.bundles.values(), deployment.resToBnd, resolver.getWiring());
    }
    if (noRefreshUnmanaged) {
        toRefresh.keySet().removeAll(flatten(unmanagedBundles));
    }
    // Automatically turn unmanaged bundles into managed bundles
    // if they are required by a feature and no other unmanaged
    // bundles have a requirement on it
    // sort is only used for display
    Set<Bundle> toManage = new TreeSet<>(new BundleComparator());
    if (!noManageBundles) {
        Set<Resource> features = resolver.getFeatures().keySet();
        Set<? extends Resource> unmanaged = apply(flatten(unmanagedBundles), adapt(BundleRevision.class));
        Set<Resource> requested = new HashSet<>();
        // Gather bundles required by a feature
        if (resolver != null && resolver.getWiring() != null) {
            for (List<Wire> wires : resolver.getWiring().values()) {
                for (Wire wire : wires) {
                    if (features.contains(wire.getRequirer()) && unmanaged.contains(wire.getProvider())) {
                        requested.add(wire.getProvider());
                    }
                }
            }
        }
        // Now, we know which bundles are completely unmanaged
        unmanaged.removeAll(requested);
        // Check if bundles have wires from really unmanaged bundles
        if (resolver != null && resolver.getWiring() != null) {
            for (List<Wire> wires : resolver.getWiring().values()) {
                for (Wire wire : wires) {
                    if (requested.contains(wire.getProvider()) && unmanaged.contains(wire.getRequirer())) {
                        requested.remove(wire.getProvider());
                    }
                }
            }
        }
        if (!requested.isEmpty()) {
            Map<Long, String> bundleToRegion = new HashMap<>();
            for (Map.Entry<String, Set<Long>> entry : dstate.bundlesPerRegion.entrySet()) {
                for (long id : entry.getValue()) {
                    bundleToRegion.put(id, entry.getKey());
                }
            }
            for (Resource rev : requested) {
                Bundle bundle = ((BundleRevision) rev).getBundle();
                long id = bundle.getBundleId();
                addToMapSet(managedBundles, bundleToRegion.get(id), id);
                toManage.add(bundle);
            }
        }
    }
    Set<Bundle> toStart = new HashSet<>();
    Set<Bundle> toResolve = new HashSet<>();
    Set<Bundle> toStop = new HashSet<>();
    //
    // Compute bundle states
    //
    Map<Resource, FeatureState> states = new HashMap<>();
    // Find all features state
    Map<Resource, FeatureState> featuresState = new HashMap<>();
    Map<Resource, Set<Resource>> conditionals = new HashMap<>();
    for (Map.Entry<String, Set<Resource>> entry : resolver.getFeaturesPerRegions().entrySet()) {
        String region = entry.getKey();
        Map<String, String> fss = stateFeatures.get(region);
        for (Resource feature : entry.getValue()) {
            Set<Resource> conditions = new HashSet<>();
            for (Wire wire : resolver.getWiring().get(feature)) {
                if (IDENTITY_NAMESPACE.equals(wire.getRequirement().getNamespace()) && FeatureResource.CONDITIONAL_TRUE.equals(wire.getRequirement().getDirectives().get(FeatureResource.REQUIREMENT_CONDITIONAL_DIRECTIVE))) {
                    conditions.add(wire.getProvider());
                }
            }
            if (conditions.isEmpty()) {
                String fs = fss.get(getFeatureId(feature));
                featuresState.put(feature, FeatureState.valueOf(fs));
            } else {
                conditionals.put(feature, conditions);
            }
        }
    }
    // Compute conditional features state
    for (Resource feature : conditionals.keySet()) {
        FeatureState state = null;
        for (Resource cond : conditionals.get(feature)) {
            FeatureState s = featuresState.get(cond);
            if (state == null) {
                state = s;
            } else if (state == FeatureState.Started && s == FeatureState.Resolved) {
                state = FeatureState.Resolved;
            }
        }
        featuresState.put(feature, state);
    }
    // Propagate Resolved state
    for (Resource feature : featuresState.keySet()) {
        if (featuresState.get(feature) == FeatureState.Resolved) {
            propagateState(states, feature, FeatureState.Resolved, resolver);
        }
    }
    // Propagate Started state
    for (Resource feature : featuresState.keySet()) {
        if (featuresState.get(feature) == FeatureState.Started) {
            propagateState(states, feature, FeatureState.Started, resolver);
        }
    }
    // Put default Started state for other bundles if start attribute is true
    for (Resource resource : resolver.getBundles().keySet()) {
        BundleInfo bundleInfo = null;
        for (Map.Entry<String, Map<String, BundleInfo>> bis : resolver.getBundleInfos().entrySet()) {
            bundleInfo = bis.getValue().get(getUri(resource));
        }
        Bundle bundle = deployment.resToBnd.get(resource);
        if (bundle == null) {
            // we are using bundleInfo and start flag
            if (bundleInfo != null && bundleInfo.isStart()) {
                states.put(resource, FeatureState.Started);
            } else {
                states.put(resource, FeatureState.Resolved);
            }
        } else {
            // if the bundle is already there, just ignore changing state by feature
            states.remove(resource);
        }
    }
    // Only keep bundles resources
    states.keySet().retainAll(resolver.getBundles().keySet());
    //
    for (Map.Entry<Resource, FeatureState> entry : states.entrySet()) {
        Bundle bundle = deployment.resToBnd.get(entry.getKey());
        if (bundle != null) {
            switch(entry.getValue()) {
                case Started:
                    toResolve.add(bundle);
                    toStart.add(bundle);
                    break;
                case Resolved:
                    toResolve.add(bundle);
                    toStop.add(bundle);
                    break;
            }
        }
    }
    //
    // Compute bundle all start levels and start levels to update
    //
    Map<Resource, Integer> startLevels = new HashMap<>();
    Map<Bundle, Integer> toUpdateStartLevel = new HashMap<>();
    for (Map.Entry<String, Set<Resource>> entry : resolver.getBundlesPerRegions().entrySet()) {
        String region = entry.getKey();
        for (Resource resource : entry.getValue()) {
            BundleInfo bi = bundleInfos.get(region).get(getUri(resource));
            if (bi != null) {
                int sl = bi.getStartLevel() > 0 ? bi.getStartLevel() : dstate.initialBundleStartLevel;
                startLevels.put(resource, sl);
                Bundle bundle = deployment.resToBnd.get(resource);
                if (bundle != null) {
                    int curSl = bundle.adapt(BundleStartLevel.class).getStartLevel();
                    if (sl != curSl) {
                        toUpdateStartLevel.put(bundle, sl);
                        if (sl > dstate.currentStartLevel) {
                            toStop.add(bundle);
                        }
                    }
                }
            }
        }
    }
    //
    if (showWiring) {
        logWiring(resolver.getWiring(), showFeaturesWiringOnly);
    }
    //
    // Log deployment
    //
    logDeployment(deployment, verbose);
    if (simulate) {
        if (!noRefresh && !toRefresh.isEmpty()) {
            print("  Bundles to refresh:", verbose);
            for (Map.Entry<Bundle, String> entry : toRefresh.entrySet()) {
                Bundle bundle = entry.getKey();
                print("    " + bundle.getSymbolicName() + "/" + bundle.getVersion() + " (" + entry.getValue() + ")", verbose);
            }
        }
        if (!toManage.isEmpty()) {
            print("  Managing bundle:", verbose);
            for (Bundle bundle : toManage) {
                print("    " + bundle.getSymbolicName() + "/" + bundle.getVersion(), verbose);
            }
        }
        return;
    }
    //
    // Execute deployment
    //
    // #1: stop bundles that needs to be updated or uninstalled in order
    // #2: uninstall needed bundles
    // #3: update regions
    // #4: update bundles
    // #5: install bundles
    // #6: save state
    // #7: install configuration
    // #8: refresh bundles
    // #9: start bundles in order
    // #10: send events
    //
    Bundle serviceBundle = dstate.serviceBundle;
    //
    // Handle updates on the FeaturesService bundle
    //
    Deployer.RegionDeployment rootRegionDeployment = deployment.regions.get(ROOT_REGION);
    // We don't support uninstalling the bundle
    if (rootRegionDeployment != null && rootRegionDeployment.toDelete.contains(serviceBundle)) {
        throw new UnsupportedOperationException("Uninstalling the FeaturesService bundle is not supported");
    }
    // When restarting, the resolution will be attempted again
    if (rootRegionDeployment != null && rootRegionDeployment.toUpdate.containsKey(serviceBundle)) {
        callback.persistResolveRequest(request);
        // save the new checksum persistently
        if (deployment.bundleChecksums.containsKey(serviceBundle.getBundleId())) {
            State state = dstate.state.copy();
            state.bundleChecksums.put(serviceBundle.getBundleId(), deployment.bundleChecksums.get(serviceBundle.getBundleId()));
            callback.saveState(state);
        }
        Resource resource = rootRegionDeployment.toUpdate.get(serviceBundle);
        String uri = getUri(resource);
        print("The FeaturesService bundle needs is being updated with " + uri, verbose);
        toRefresh.clear();
        toRefresh.put(serviceBundle, "FeaturesService bundle is being updated");
        computeBundlesToRefresh(toRefresh, dstate.bundles.values(), Collections.emptyMap(), Collections.emptyMap());
        installSupport.stopBundle(serviceBundle, STOP_TRANSIENT);
        try (InputStream is = getBundleInputStream(resource, providers)) {
            installSupport.updateBundle(serviceBundle, uri, is);
        }
        installSupport.refreshPackages(toRefresh.keySet());
        installSupport.startBundle(serviceBundle);
        return;
    }
    callback.callListeners(DeploymentEvent.DEPLOYMENT_STARTED);
    //
    for (Deployer.RegionDeployment regionDeployment : deployment.regions.values()) {
        toStop.addAll(regionDeployment.toUpdate.keySet());
        toStop.addAll(regionDeployment.toDelete);
    }
    removeFragmentsAndBundlesInState(toStop, UNINSTALLED | RESOLVED | STOPPING);
    if (!toStop.isEmpty()) {
        print("Stopping bundles:", verbose);
        while (!toStop.isEmpty()) {
            List<Bundle> bs = getBundlesToStop(toStop);
            for (Bundle bundle : bs) {
                print("  " + bundle.getSymbolicName() + "/" + bundle.getVersion(), verbose);
                // If the bundle start level will be changed, stop it persistently to
                // avoid a restart when the start level is actually changed
                installSupport.stopBundle(bundle, toUpdateStartLevel.containsKey(bundle) ? 0 : STOP_TRANSIENT);
                toStop.remove(bundle);
            }
        }
    }
    //
    // Delete bundles
    //
    boolean hasToDelete = false;
    for (Deployer.RegionDeployment regionDeployment : deployment.regions.values()) {
        if (hasToDelete = !regionDeployment.toDelete.isEmpty()) {
            break;
        }
    }
    if (hasToDelete) {
        print("Uninstalling bundles:", verbose);
        for (Map.Entry<String, Deployer.RegionDeployment> entry : deployment.regions.entrySet()) {
            String name = entry.getKey();
            Deployer.RegionDeployment regionDeployment = entry.getValue();
            for (Bundle bundle : regionDeployment.toDelete) {
                print("  " + bundle.getSymbolicName() + "/" + bundle.getVersion(), verbose);
                installSupport.uninstall(bundle);
                removeFromMapSet(managedBundles, name, bundle.getBundleId());
            }
        }
    }
    //
    // Update regions
    //
    {
        // Add bundles
        Map<String, Set<Long>> bundles = new HashMap<>();
        add(bundles, apply(unmanagedBundles, bundleId()));
        add(bundles, managedBundles);
        // Compute policies
        RegionDigraph computedDigraph = resolver.getFlatDigraph();
        Map<String, Map<String, Map<String, Set<String>>>> policies = copy(dstate.filtersPerRegion);
        // Only keep regions which still have bundles
        policies.keySet().retainAll(bundles.keySet());
        // Fix broken filters
        for (String name : policies.keySet()) {
            policies.get(name).keySet().retainAll(policies.keySet());
        }
        // Update managed regions
        for (Region computedRegion : computedDigraph.getRegions()) {
            String name = computedRegion.getName();
            Map<String, Map<String, Set<String>>> policy = policies.computeIfAbsent(name, k -> new HashMap<>());
            for (RegionDigraph.FilteredRegion fr : computedRegion.getEdges()) {
                String r2 = fr.getRegion().getName();
                Map<String, Set<String>> filters = new HashMap<>();
                Map<String, Collection<String>> current = fr.getFilter().getSharingPolicy();
                for (String ns : current.keySet()) {
                    for (String f : current.get(ns)) {
                        addToMapSet(filters, ns, f);
                    }
                }
                policy.put(r2, filters);
            }
        }
        // Apply all changes
        installSupport.replaceDigraph(policies, bundles);
    }
    //
    // Update bundles
    //
    boolean hasToUpdate = false;
    for (Deployer.RegionDeployment regionDeployment : deployment.regions.values()) {
        if (hasToUpdate = !regionDeployment.toUpdate.isEmpty()) {
            break;
        }
    }
    if (hasToUpdate) {
        print("Updating bundles:", verbose);
        for (Map.Entry<String, Deployer.RegionDeployment> rde : deployment.regions.entrySet()) {
            for (Map.Entry<Bundle, Resource> entry : rde.getValue().toUpdate.entrySet()) {
                Bundle bundle = entry.getKey();
                Resource resource = entry.getValue();
                String uri = getUri(resource);
                print("  " + uri, verbose);
                try (InputStream is = getBundleInputStream(resource, providers)) {
                    installSupport.updateBundle(bundle, uri, is);
                }
                toStart.add(bundle);
            }
        }
    }
    //
    for (Map.Entry<Bundle, Integer> entry : toUpdateStartLevel.entrySet()) {
        Bundle bundle = entry.getKey();
        int sl = entry.getValue();
        bundle.adapt(BundleStartLevel.class).setStartLevel(sl);
    }
    //
    // Install bundles
    //
    boolean hasToInstall = false;
    for (Deployer.RegionDeployment regionDeployment : deployment.regions.values()) {
        if (hasToInstall = !regionDeployment.toInstall.isEmpty()) {
            break;
        }
    }
    if (hasToInstall) {
        print("Installing bundles:", verbose);
        Map<Bundle, Integer> customStartLevels = new HashMap<>();
        for (Map.Entry<String, Deployer.RegionDeployment> entry : deployment.regions.entrySet()) {
            String name = entry.getKey();
            Deployer.RegionDeployment regionDeployment = entry.getValue();
            for (Resource resource : regionDeployment.toInstall) {
                String uri = getUri(resource);
                print("  " + uri, verbose);
                Bundle bundle;
                long crc;
                try (ChecksumUtils.CRCInputStream is = new ChecksumUtils.CRCInputStream(getBundleInputStream(resource, providers))) {
                    bundle = installSupport.installBundle(name, uri, is);
                    crc = is.getCRC();
                }
                addToMapSet(managedBundles, name, bundle.getBundleId());
                deployment.resToBnd.put(resource, bundle);
                // save a checksum of installed snapshot bundle
                if (UPDATE_SNAPSHOTS_CRC.equals(request.updateSnaphots) && isUpdateable(resource) && !deployment.bundleChecksums.containsKey(bundle.getBundleId())) {
                    deployment.bundleChecksums.put(bundle.getBundleId(), crc);
                }
                Integer startLevel = startLevels.get(resource);
                if (startLevel != null && startLevel != dstate.initialBundleStartLevel) {
                    customStartLevels.put(bundle, startLevel);
                }
                FeatureState reqState = states.get(resource);
                if (reqState == null) {
                    reqState = FeatureState.Started;
                }
                switch(reqState) {
                    case Started:
                        toResolve.add(bundle);
                        toStart.add(bundle);
                        break;
                    case Resolved:
                        toResolve.add(bundle);
                        break;
                }
            }
        }
        // Set start levels after install to avoid starting before all bundles are installed
        for (Bundle bundle : customStartLevels.keySet()) {
            int startLevel = customStartLevels.get(bundle);
            bundle.adapt(BundleStartLevel.class).setStartLevel(startLevel);
        }
    }
    //
    // Update and save state
    //
    State newState = new State();
    newState.bundleChecksums.putAll(deployment.bundleChecksums);
    newState.requirements.putAll(request.requirements);
    newState.installedFeatures.putAll(installedFeatures);
    newState.stateFeatures.putAll(stateFeatures);
    newState.managedBundles.putAll(managedBundles);
    callback.saveState(newState);
    //
    if (!newFeatures.isEmpty()) {
        Set<String> featureIds = flatten(newFeatures);
        for (Feature feature : dstate.features.values()) {
            if (featureIds.contains(feature.getId())) {
                installSupport.installConfigs(feature);
                installSupport.installLibraries(feature);
            }
            for (Conditional cond : feature.getConditional()) {
                Feature condFeature = cond.asFeature();
                if (featureIds.contains(condFeature.getId())) {
                    installSupport.installConfigs(condFeature);
                    installSupport.installLibraries(condFeature);
                }
            }
        }
    }
    if (!noRefresh) {
        if (toRefresh.containsKey(dstate.bundles.get(0l))) {
            print("The system bundle needs to be refreshed, restarting Karaf...", verbose);
            System.setProperty("karaf.restart", "true");
            dstate.bundles.get(0l).stop();
            return;
        }
        toStop = new HashSet<>();
        toStop.addAll(toRefresh.keySet());
        removeFragmentsAndBundlesInState(toStop, UNINSTALLED | RESOLVED | STOPPING);
        if (!toStop.isEmpty()) {
            print("Stopping bundles:", verbose);
            while (!toStop.isEmpty()) {
                List<Bundle> bs = getBundlesToStop(toStop);
                for (Bundle bundle : bs) {
                    print("  " + bundle.getSymbolicName() + "/" + bundle.getVersion(), verbose);
                    installSupport.stopBundle(bundle, STOP_TRANSIENT);
                    toStop.remove(bundle);
                    toStart.add(bundle);
                }
            }
        }
        if (!toRefresh.isEmpty()) {
            print("Refreshing bundles:", verbose);
            for (Map.Entry<Bundle, String> entry : toRefresh.entrySet()) {
                Bundle bundle = entry.getKey();
                print("    " + bundle.getSymbolicName() + "/" + bundle.getVersion() + " (" + entry.getValue() + ")", verbose);
            }
            // Ensure all classes are loaded in case the bundle will be refreshed
            if (serviceBundle != null && toRefresh.containsKey(serviceBundle)) {
                ensureAllClassesLoaded(serviceBundle);
            }
            installSupport.refreshPackages(toRefresh.keySet());
        }
    }
    // Resolve bundles
    toResolve.addAll(toStart);
    toResolve.addAll(toRefresh.keySet());
    removeBundlesInState(toResolve, UNINSTALLED);
    callback.callListeners(DeploymentEvent.BUNDLES_INSTALLED);
    installSupport.resolveBundles(toResolve, resolver.getWiring(), deployment.resToBnd);
    callback.callListeners(DeploymentEvent.BUNDLES_RESOLVED);
    // Compute bundles to start
    removeFragmentsAndBundlesInState(toStart, UNINSTALLED | ACTIVE);
    if (!toStart.isEmpty()) {
        // Compute correct start order
        List<Exception> exceptions = new ArrayList<>();
        print("Starting bundles:", verbose);
        while (!toStart.isEmpty()) {
            List<Bundle> bs = getBundlesToStart(toStart, serviceBundle);
            for (Bundle bundle : bs) {
                print("  " + bundle.getSymbolicName() + "/" + bundle.getVersion(), verbose);
                try {
                    installSupport.startBundle(bundle);
                } catch (BundleException e) {
                    exceptions.add(e);
                }
                toStart.remove(bundle);
            }
        }
        if (!exceptions.isEmpty()) {
            throw new MultiException("Error restarting bundles", exceptions);
        }
    }
    // Call listeners
    for (Map.Entry<String, Set<String>> entry : delFeatures.entrySet()) {
        for (String name : entry.getValue()) {
            Feature feature = dstate.features.get(name);
            if (feature != null) {
                callback.callListeners(new FeatureEvent(FeatureEvent.EventType.FeatureUninstalled, feature, entry.getKey(), false));
            }
        }
    }
    for (Map.Entry<String, Set<String>> entry : newFeatures.entrySet()) {
        for (String name : entry.getValue()) {
            Feature feature = dstate.features.get(name);
            if (feature != null) {
                callback.callListeners(new FeatureEvent(FeatureEvent.EventType.FeatureInstalled, feature, entry.getKey(), false));
            }
        }
    }
    callback.callListeners(DeploymentEvent.DEPLOYMENT_FINISHED);
    print("Done.", verbose);
}
Also used : MultiException(org.apache.karaf.features.internal.util.MultiException) Constants(org.osgi.framework.Constants) ResolverUtil(org.apache.karaf.features.internal.resolver.ResolverUtil) URL(java.net.URL) MapUtils.diff(org.apache.karaf.features.internal.util.MapUtils.diff) FeatureResource(org.apache.karaf.features.internal.resolver.FeatureResource) Region(org.eclipse.equinox.region.Region) LoggerFactory(org.slf4j.LoggerFactory) UNINSTALLED(org.osgi.framework.Bundle.UNINSTALLED) Conditional(org.apache.karaf.features.Conditional) MapUtils.removeFromMapSet(org.apache.karaf.features.internal.util.MapUtils.removeFromMapSet) FeaturesService(org.apache.karaf.features.FeaturesService) ResourceUtils(org.apache.karaf.features.internal.resolver.ResourceUtils) ResourceUtils.getUri(org.apache.karaf.features.internal.resolver.ResourceUtils.getUri) MapUtils.copy(org.apache.karaf.features.internal.util.MapUtils.copy) Map(java.util.Map) VersionTable(org.apache.felix.utils.version.VersionTable) Bundle(org.osgi.framework.Bundle) Repository(org.osgi.service.repository.Repository) Method(java.lang.reflect.Method) BundleRevision(org.osgi.framework.wiring.BundleRevision) MapUtils.apply(org.apache.karaf.features.internal.util.MapUtils.apply) EnumSet(java.util.EnumSet) BundleException(org.osgi.framework.BundleException) ServiceReference(org.osgi.framework.ServiceReference) STOPPING(org.osgi.framework.Bundle.STOPPING) BundleInfo(org.apache.karaf.features.BundleInfo) MapUtils(org.apache.karaf.features.internal.util.MapUtils) UPDATEABLE_URIS(org.apache.karaf.features.FeaturesService.UPDATEABLE_URIS) Collection(java.util.Collection) ACTIVE(org.osgi.framework.Bundle.ACTIVE) Feature(org.apache.karaf.features.Feature) Namespace(org.osgi.resource.Namespace) MapUtils.flatten(org.apache.karaf.features.internal.util.MapUtils.flatten) Set(java.util.Set) ResourceUtils.getType(org.apache.karaf.features.internal.resolver.ResourceUtils.getType) UPDATE_SNAPSHOTS_CRC(org.apache.karaf.features.FeaturesService.UPDATE_SNAPSHOTS_CRC) MapUtils.map(org.apache.karaf.features.internal.util.MapUtils.map) Version(org.osgi.framework.Version) MapUtils.addToMapSet(org.apache.karaf.features.internal.util.MapUtils.addToMapSet) VersionRange(org.apache.felix.utils.version.VersionRange) BundleStartLevel(org.osgi.framework.startlevel.BundleStartLevel) STOP_TRANSIENT(org.osgi.framework.Bundle.STOP_TRANSIENT) IDENTITY_NAMESPACE(org.osgi.framework.namespace.IdentityNamespace.IDENTITY_NAMESPACE) List(java.util.List) ROOT_REGION(org.apache.karaf.features.FeaturesService.ROOT_REGION) Wire(org.osgi.resource.Wire) HostNamespace(org.osgi.framework.namespace.HostNamespace) DownloadManager(org.apache.karaf.features.internal.download.DownloadManager) SortedMap(java.util.SortedMap) Requirement(org.osgi.resource.Requirement) UPDATE_SNAPSHOTS_ALWAYS(org.apache.karaf.features.FeaturesService.UPDATE_SNAPSHOTS_ALWAYS) ChecksumUtils(org.apache.karaf.features.internal.util.ChecksumUtils) HashMap(java.util.HashMap) TYPE_SUBSYSTEM(org.apache.karaf.features.internal.resolver.ResourceUtils.TYPE_SUBSYSTEM) TreeSet(java.util.TreeSet) FeatureEvent(org.apache.karaf.features.FeatureEvent) RESOLVED(org.osgi.framework.Bundle.RESOLVED) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) BundleNamespace(org.osgi.framework.namespace.BundleNamespace) ResolverUtil.getVersion(org.apache.karaf.features.internal.resolver.ResolverUtil.getVersion) StreamProvider(org.apache.karaf.features.internal.download.StreamProvider) HOST_NAMESPACE(org.osgi.framework.namespace.HostNamespace.HOST_NAMESPACE) URLConnection(java.net.URLConnection) TYPE_BUNDLE(org.osgi.framework.namespace.IdentityNamespace.TYPE_BUNDLE) BundleWiring(org.osgi.framework.wiring.BundleWiring) Macro(org.apache.karaf.features.internal.util.Macro) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) Resource(org.osgi.resource.Resource) FeatureState(org.apache.karaf.features.FeatureState) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) Resolver(org.osgi.service.resolver.Resolver) ResolverUtil.getSymbolicName(org.apache.karaf.features.internal.resolver.ResolverUtil.getSymbolicName) ResourceUtils.getFeatureId(org.apache.karaf.features.internal.resolver.ResourceUtils.getFeatureId) SubsystemResolver(org.apache.karaf.features.internal.region.SubsystemResolver) TreeMap(java.util.TreeMap) PackageNamespace(org.osgi.framework.namespace.PackageNamespace) RegionDigraph(org.eclipse.equinox.region.RegionDigraph) MapUtils.add(org.apache.karaf.features.internal.util.MapUtils.add) DeploymentEvent(org.apache.karaf.features.DeploymentEvent) BundleWire(org.osgi.framework.wiring.BundleWire) Comparator(java.util.Comparator) Collections(java.util.Collections) InputStream(java.io.InputStream) BundleStartLevel(org.osgi.framework.startlevel.BundleStartLevel) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) VersionRange(org.apache.felix.utils.version.VersionRange) Conditional(org.apache.karaf.features.Conditional) Wire(org.osgi.resource.Wire) BundleWire(org.osgi.framework.wiring.BundleWire) Feature(org.apache.karaf.features.Feature) BundleInfo(org.apache.karaf.features.BundleInfo) FeatureEvent(org.apache.karaf.features.FeatureEvent) TreeSet(java.util.TreeSet) BundleRevision(org.osgi.framework.wiring.BundleRevision) BundleException(org.osgi.framework.BundleException) HashSet(java.util.HashSet) StreamProvider(org.apache.karaf.features.internal.download.StreamProvider) FeatureResource(org.apache.karaf.features.internal.resolver.FeatureResource) Resource(org.osgi.resource.Resource) SubsystemResolver(org.apache.karaf.features.internal.region.SubsystemResolver) FeatureState(org.apache.karaf.features.FeatureState) Region(org.eclipse.equinox.region.Region) Map(java.util.Map) SortedMap(java.util.SortedMap) HashMap(java.util.HashMap) TreeMap(java.util.TreeMap) MultiException(org.apache.karaf.features.internal.util.MultiException) MapUtils.removeFromMapSet(org.apache.karaf.features.internal.util.MapUtils.removeFromMapSet) EnumSet(java.util.EnumSet) Set(java.util.Set) MapUtils.addToMapSet(org.apache.karaf.features.internal.util.MapUtils.addToMapSet) TreeSet(java.util.TreeSet) HashSet(java.util.HashSet) RegionDigraph(org.eclipse.equinox.region.RegionDigraph) Bundle(org.osgi.framework.Bundle) FileInputStream(java.io.FileInputStream) InputStream(java.io.InputStream) TreeMap(java.util.TreeMap) FeatureState(org.apache.karaf.features.FeatureState) MultiException(org.apache.karaf.features.internal.util.MultiException) BundleException(org.osgi.framework.BundleException) IOException(java.io.IOException) ChecksumUtils(org.apache.karaf.features.internal.util.ChecksumUtils)

Example 2 with MultiException

use of org.apache.karaf.features.internal.util.MultiException in project karaf by apache.

the class FeaturesServiceTest method testInstallBatchFeatureWithFailure.

@Test
@Ignore("Currently takes too long")
public void testInstallBatchFeatureWithFailure() throws Exception {
    String bundle1Uri = "file:bundle1";
    String bundle2Uri = "file:bundle2";
    URI uri = createTempRepo(FEATURE_WITH_INVALID_BUNDLE, bundle1Uri, bundle2Uri);
    BundleInstallSupport installSupport = EasyMock.niceMock(BundleInstallSupport.class);
    expect(installSupport.getInfo()).andReturn(dummyInfo());
    EasyMock.replay(installSupport);
    FeaturesServiceConfig cfg = new FeaturesServiceConfig();
    FeaturesServiceImpl svc = new FeaturesServiceImpl(new Storage(), null, null, resolver, installSupport, null, cfg);
    svc.addRepository(uri);
    try {
        List<String> features = new ArrayList<>();
        for (Feature feature : svc.listFeatures()) {
            features.add(feature.getId());
        }
        Collections.reverse(features);
        svc.installFeatures(new CopyOnWriteArraySet<>(features), EnumSet.noneOf(FeaturesService.Option.class));
        fail("Call should have thrown an exception");
    } catch (MultiException e) {
        Throwable suppressed = e.getSuppressed()[0];
        Assert.assertEquals("Error downloading zfs:unknown", suppressed.getMessage());
    }
}
Also used : FeaturesServiceImpl(org.apache.karaf.features.internal.service.FeaturesServiceImpl) BundleInstallSupport(org.apache.karaf.features.internal.service.BundleInstallSupport) ArrayList(java.util.ArrayList) URI(java.net.URI) StateStorage(org.apache.karaf.features.internal.service.StateStorage) FeaturesServiceConfig(org.apache.karaf.features.internal.service.FeaturesServiceConfig) MultiException(org.apache.karaf.features.internal.util.MultiException) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 3 with MultiException

use of org.apache.karaf.features.internal.util.MultiException in project karaf by apache.

the class VerifyMojo method doExecute.

protected void doExecute() throws MojoExecutionException, MojoFailureException {
    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");
        }
        allDescriptors.add("file:" + project.getBuild().getDirectory() + "/feature/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);
    }
    List<Exception> failures = new ArrayList<>();
    for (Feature feature : featuresToTest) {
        try {
            String id = feature.getName() + "/" + feature.getVersion();
            verifyResolution(new CustomDownloadManager(resolver, executor), repositories, Collections.singleton(id), properties);
            getLog().info("Verification of feature " + id + " succeeded");
        } catch (Exception e) {
            if (e.getCause() instanceof ResolutionException) {
                getLog().warn(e.getMessage());
            } else {
                getLog().warn(e);
            }
            failures.add(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());
            try {
                verifyResolution(manager, repositories, ids, properties);
                getLog().info("Verification of feature " + ids + " 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) {
                        getLog().warn("Feature resolution failed for " + ids + "\nMessage: " + e.getCause().getMessage());
                        continue;
                    }
                }
                if (e.getCause() instanceof ResolutionException) {
                    getLog().warn(e.getMessage());
                } else {
                    getLog().warn(e);
                }
                failures.add(e);
                if ("first".equals(fail)) {
                    throw e;
                }
            }
        }
    }
    if ("end".equals(fail) && !failures.isEmpty()) {
        throw new MojoExecutionException("Verification failures", new MultiException("Verification failures", failures));
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Reader(java.io.Reader) FileReader(java.io.FileReader) Conditional(org.apache.karaf.features.internal.model.Conditional) Properties(java.util.Properties) CustomDownloadManager(org.apache.karaf.profile.assembly.CustomDownloadManager) DownloadManager(org.apache.karaf.features.internal.download.DownloadManager) Feature(org.apache.karaf.features.internal.model.Feature) Field(java.lang.reflect.Field) FileReader(java.io.FileReader) Features(org.apache.karaf.features.internal.model.Features) List(java.util.List) ArrayList(java.util.ArrayList) Pattern(java.util.regex.Pattern) ScheduledExecutorService(java.util.concurrent.ScheduledExecutorService) MojoExecutionException(org.apache.maven.plugin.MojoExecutionException) ConfigFile(org.apache.karaf.features.internal.model.ConfigFile) Hashtable(java.util.Hashtable) IOException(java.io.IOException) MultiException(org.apache.karaf.features.internal.util.MultiException) BundleException(org.osgi.framework.BundleException) InvalidSyntaxException(org.osgi.framework.InvalidSyntaxException) ResolutionException(org.osgi.service.resolver.ResolutionException) IOException(java.io.IOException) MojoExecutionException(org.apache.maven.plugin.MojoExecutionException) MojoFailureException(org.apache.maven.plugin.MojoFailureException) ResolutionException(org.osgi.service.resolver.ResolutionException) BundleRequirement(org.osgi.framework.wiring.BundleRequirement) Requirement(org.osgi.resource.Requirement) Collection(java.util.Collection) CustomDownloadManager(org.apache.karaf.profile.assembly.CustomDownloadManager) MultiException(org.apache.karaf.features.internal.util.MultiException)

Aggregations

ArrayList (java.util.ArrayList)3 MultiException (org.apache.karaf.features.internal.util.MultiException)3 IOException (java.io.IOException)2 Collection (java.util.Collection)2 HashMap (java.util.HashMap)2 List (java.util.List)2 DownloadManager (org.apache.karaf.features.internal.download.DownloadManager)2 FileInputStream (java.io.FileInputStream)1 FileReader (java.io.FileReader)1 InputStream (java.io.InputStream)1 Reader (java.io.Reader)1 Field (java.lang.reflect.Field)1 Method (java.lang.reflect.Method)1 URI (java.net.URI)1 URL (java.net.URL)1 URLConnection (java.net.URLConnection)1 Collections (java.util.Collections)1 Comparator (java.util.Comparator)1 EnumSet (java.util.EnumSet)1 HashSet (java.util.HashSet)1