All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.galasa.framework.BundleManagement Maven / Gradle / Ivy

There is a newer version: 0.37.0
Show newest version
/*
 * Copyright contributors to the Galasa project
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package dev.galasa.framework;

import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.text.*;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.felix.bundlerepository.Capability;
import org.apache.felix.bundlerepository.Property;
import org.apache.felix.bundlerepository.Reason;
import org.apache.felix.bundlerepository.RepositoryAdmin;
import org.apache.felix.bundlerepository.Resolver;
import org.apache.felix.bundlerepository.Resource;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;

import dev.galasa.framework.spi.FrameworkException;

public class BundleManagement {

    private static final Log logger = LogFactory.getLog(BundleManagement.class);

    /**
     * Load a bundle from the OSGi Bundle Repository
     * @param repositoryAdmin
     * @param bundleContext
     * @param bundleSymbolicName
     * @throws FrameworkException
     */
    public static void loadBundle(RepositoryAdmin repositoryAdmin, BundleContext bundleContext, String bundleSymbolicName) throws FrameworkException {

        logger.trace("Installing bundle " + bundleSymbolicName);
        Resolver resolver = repositoryAdmin.resolver();
        String filterString = "(symbolicname=" + bundleSymbolicName + ")";
        Resource[] resources = null;
        try {
            resources = repositoryAdmin.discoverResources(filterString);
        } catch (InvalidSyntaxException e) {
            throw new FrameworkException("Unable to discover repoistory resources", e);
        }
        try {
            if (resources.length == 0) {
                throw new FrameworkException("Unable to locate bundle \"" + bundleSymbolicName + "\" in OBR repository");
            }
            // *** Only load the first one
            addResource(bundleContext, bundleSymbolicName, resolver, resources[0]);
        } catch (FrameworkException e) {
            throw new FrameworkException("Unable to install bundle \"" + bundleSymbolicName + "\" from OBR repository",
                    e);
        }
    }

    public static void loadAllGherkinManagerBundles(RepositoryAdmin repositoryAdmin, BundleContext bundleContext) throws FrameworkException {
        logger.trace("Installing manager bundles");
        Resolver resolver = repositoryAdmin.resolver();
        String filterString = "(symbolicname=*)";
        Resource[] resources = null;
        try {
            resources = repositoryAdmin.discoverResources(filterString);
        } catch (InvalidSyntaxException e) {
            throw new FrameworkException("Unable to discover repoistory resources", e);
        }
        try {
            if (resources.length == 0) {
                throw new FrameworkException("Unable to locate manager bundles in OBR repository");
            }

            //*** Load only bundles that are not already resolved
            for(Resource resource : resources) {
                boolean gherkinSupport = false;
                Capability[] capabilities = resource.getCapabilities();
                for(Capability capability : capabilities) {
                    if(capability.getName().equals("service")) {
                        for(Property prop : capability.getProperties()) {
                            if(prop.getValue().contains("dev.galasa.framework.spi.IGherkinManager") && prop.getValue().contains("dev.galasa.framework.spi.IManager")) {
                                gherkinSupport = true;
                            }
                        }
                    }
                }
                if(gherkinSupport) {
                    if (!isBundleActive(bundleContext, resource.getSymbolicName())) {
                        addResource(bundleContext, resource.getSymbolicName(), resolver, resource);
                    }
                }
            }
        } catch (FrameworkException e) {
            throw new FrameworkException("Unable to install manager bundles from OBR repository",
                    e);
        }
    }

    /**
     * Add the Resource to the Resolver and resolve
     * 
     * @param bundleSymbolicName
     * @param resolver
     * @param resource
     * @throws LauncherException
     */
    private static void addResource(BundleContext bundleContext, String bundleSymbolicName, Resolver resolver, Resource resource) throws FrameworkException {
        logger.trace("Resouce: " + resource);
        resolver.add(resource);

        boolean resourceHasReferenceUrl = false;
        if (resource.getURI().startsWith("reference:")) {
            resourceHasReferenceUrl = true;
        }

        if (resolver.resolve()) {
            Resource[] requiredResources = resolver.getRequiredResources();
            for (Resource requiredResource : requiredResources) {
                if (requiredResource.getURI().startsWith("reference:")) {
                    resourceHasReferenceUrl = true;
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("  RequiredResource: " + requiredResource.getSymbolicName());

                }
            }
            Resource[] optionalResources = resolver.getOptionalResources();
            for (Resource optionalResource : optionalResources) {
                if (optionalResource.getURI().startsWith("reference:")) {
                    resourceHasReferenceUrl = true;
                }
                if (logger.isTraceEnabled()) {
                    logger.trace("  OptionalResource: " + optionalResource.getSymbolicName());
                }
            }


            if (!resourceHasReferenceUrl) {
                resolver.deploy(Resolver.START);
            } else {
                // *** The Resolver can't cope with reference: URIs which is valid for Felix.
                // *** So we have to manually install and start the bundles if ANY bundle
                // *** is a reference
                ArrayList bundlesToStart = new ArrayList<>();
                try {

                    Resource[] startRequiredResources = resolver.getRequiredResources();
                    for (Resource requiredResource : startRequiredResources) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("  startRequiredResource: adding resource" +requiredResource.getURI().toString());
                        }
                        bundlesToStart.add(bundleContext.installBundle(requiredResource.getURI().toString()));
                    }
                    Resource[] startOptionalResources = resolver.getOptionalResources();
                    for (Resource optionalResource : startOptionalResources) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("  getOptionalResources: adding resource" +optionalResource.getURI().toString());
                        }
                        bundlesToStart.add(bundleContext.installBundle(optionalResource.getURI().toString()));
                    }

                    bundlesToStart.add(bundleContext.installBundle(resource.getURI().toString()));
                    for (Bundle bundle : bundlesToStart) {
                        if (logger.isTraceEnabled()) {
                            logger.trace("  bundlesToStart: starting" +bundle.getClass().toString());
                        }
                        bundle.start();
                    }
                } catch (Exception e) {
                    throw new FrameworkException("Unable to install bundles outside of resolver", e);
                }
            }

            if (!isBundleActive(bundleContext, bundleSymbolicName)) {
                String msg = MessageFormat.format("Bundle ''{0}'' failed to install and activate",bundleSymbolicName);
                throw new FrameworkException(msg);
            }

            printBundles(bundleContext);
        } else {
            logger.error("Unable to resolve " + resource.toString());
            Reason[] unsatisfiedRequirements = resolver.getUnsatisfiedRequirements();
            for (Reason reason : unsatisfiedRequirements) {
                logger.error("Unsatisfied requirement: " + reason.getRequirement());
            }
            throw new FrameworkException("Unable to resolve bundle " + bundleSymbolicName);
        }

    }

    /**
     * Is the supplied active in the OSGi framework
     * @param bundleContext
     * @param bundleSymbolicName
     * @return true if it is ib the or false
     */
    public static boolean isBundleActive(BundleContext bundleContext, String bundleSymbolicName) {
        Bundle[] bundles = bundleContext.getBundles();
        for (Bundle bundle : bundles) {
            if (bundle.getSymbolicName().equals(bundleSymbolicName) && bundle.getState() == Bundle.ACTIVE) {
                return true;
            }
        }

        return false;
    }

    /**
     * Print the currently installed bundles and their state
     */
    private static void printBundles(BundleContext bundleContext) {
        if (!logger.isTraceEnabled()) {
            return;
        }
        // Get the bundles
        Bundle[] bundles = bundleContext.getBundles();
        // Format and print the bundle Id, State, Symbolic name and Version.
        StringBuilder messageBuffer = new StringBuilder(2048);
        messageBuffer.append("Bundle status:");

        for (Bundle bundle : bundles) {
            String gitHash = "";
            try {
                URL githashUrl = bundle.getEntry("/META-INF/git.hash");
                if (githashUrl != null) {
                    try (InputStream is = githashUrl.openStream()) {
                        gitHash = "-" + IOUtils.toString(is, StandardCharsets.UTF_8);
                    }
                }
            } catch(Exception e) {}
            
            String bundleId = String.valueOf(bundle.getBundleId());
            messageBuffer.append("\n").append(String.format("%5s", bundleId)).append("|")
                    .append(String.format("%-11s", getBundleStateLabel(bundle))).append("|     |")
                    .append(bundle.getSymbolicName()).append(" (")
                    .append(bundle.getVersion()).append(gitHash).append(")");
        }

        logger.trace(messageBuffer.toString());
    }

    /**
     * Convert bundle state to string
     * 
     * @param bundle
     * @return The bundle state
     */
    private static String getBundleStateLabel(Bundle bundle) {
        switch (bundle.getState()) {
            case Bundle.UNINSTALLED:
                return "Uninstalled";
            case Bundle.INSTALLED:
                return "Installed";
            case Bundle.RESOLVED:
                return "Resolved";
            case Bundle.STARTING:
                return "Starting";
            case Bundle.STOPPING:
                return "Stopping";
            case Bundle.ACTIVE:
                return "Active";
            default:
                return "";
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy