Search in sources :

Example 56 with ExportPackageDescription

use of org.eclipse.osgi.service.resolver.ExportPackageDescription in project rt.equinox.framework by eclipse.

the class ResolverBundle method attachFragment.

void attachFragment(ResolverBundle fragment, boolean dynamicAttach) {
    if (isFragment())
        // cannot attach to fragments;
        return;
    if (!getBundleDescription().attachFragments() || (isResolved() && !getBundleDescription().dynamicFragments()))
        // host is restricting attachment
        return;
    if (fragment.getHost().getNumPossibleSuppliers() > 0 && !((HostSpecification) fragment.getHost().getVersionConstraint()).isMultiHost())
        // fragment is restricting attachment
        return;
    ImportPackageSpecification[] newImports = fragment.getBundleDescription().getImportPackages();
    BundleSpecification[] newRequires = fragment.getBundleDescription().getRequiredBundles();
    ExportPackageDescription[] newExports = fragment.getBundleDescription().getExportPackages();
    GenericDescription[] newGenericCapabilities = fragment.getBundleDescription().getGenericCapabilities();
    GenericSpecification[] newGenericRequires = fragment.getBundleDescription().getGenericRequires();
    // if this is not during initialization then check if constraints conflict
    if (dynamicAttach && constraintsConflict(fragment.getBundleDescription(), newImports, newRequires, newGenericRequires))
        // do not allow fragments with conflicting constraints
        return;
    if (isResolved() && newExports.length > 0)
        fragment.setNewFragmentExports(true);
    initFragments();
    // already attached to this host
    for (Iterator<ResolverBundle> iFragments = fragments.iterator(); iFragments.hasNext(); ) {
        ResolverBundle existingFragment = iFragments.next();
        String bsn = existingFragment.getName();
        if (bsn != null && bsn.equals(fragment.getName()))
            return;
    }
    if (fragments.contains(fragment))
        return;
    fragments.add(fragment);
    fragment.getHost().addPossibleSupplier(this);
    if (newImports.length > 0) {
        ArrayList<ResolverImport> hostImports = new ArrayList<>(newImports.length);
        for (int i = 0; i < newImports.length; i++) if (!isImported(newImports[i].getName()))
            hostImports.add(new ResolverImport(this, newImports[i]));
        fragmentImports.put(fragment.bundleID, hostImports);
    }
    if (newRequires.length > 0) {
        ArrayList<BundleConstraint> hostRequires = new ArrayList<>(newRequires.length);
        for (int i = 0; i < newRequires.length; i++) if (!isRequired(newRequires[i].getName()))
            hostRequires.add(new BundleConstraint(this, newRequires[i]));
        fragmentRequires.put(fragment.bundleID, hostRequires);
    }
    if (newGenericRequires.length > 0) {
        ArrayList<GenericConstraint> hostGenericRequires = new ArrayList<>(newGenericRequires.length);
        for (int i = 0; i < newGenericRequires.length; i++) {
            // only add namespaces that are not osgi.ee
            if (!StateImpl.OSGI_EE_NAMESPACE.equals(newGenericRequires[i].getType())) {
                hostGenericRequires.add(new GenericConstraint(this, newGenericRequires[i], resolver.isDevelopmentMode()));
            }
        }
        if (!hostGenericRequires.isEmpty())
            fragmentGenericRequires.put(fragment.bundleID, hostGenericRequires);
    }
    ArrayList<ResolverExport> hostExports = new ArrayList<>(newExports.length);
    if (newExports.length > 0 && dynamicAttach) {
        for (int i = 0; i < newExports.length; i++) {
            ResolverExport[] currentExports = getExports(newExports[i].getName());
            boolean foundEquivalent = false;
            for (int j = 0; j < currentExports.length && !foundEquivalent; j++) {
                if (equivalentExports(currentExports[j], newExports[i]))
                    foundEquivalent = true;
            }
            if (!foundEquivalent) {
                ExportPackageDescription hostExport = new ExportPackageDescriptionImpl(getBundleDescription(), newExports[i]);
                hostExports.add(new ResolverExport(this, hostExport));
            }
        }
        fragmentExports.put(fragment.bundleID, hostExports);
    }
    List<GenericCapability> hostCapabilities = new ArrayList<>(newGenericCapabilities.length);
    if (newGenericCapabilities.length > 0 && dynamicAttach) {
        for (GenericDescription capability : newGenericCapabilities) {
            if (!IdentityNamespace.IDENTITY_NAMESPACE.equals(capability.getType())) {
                GenericDescription hostCapabililty = new GenericDescriptionImpl(getBundleDescription(), capability);
                hostCapabilities.add(new GenericCapability(this, hostCapabililty, resolver.isDevelopmentMode()));
            }
        }
        if (hostCapabilities.size() > 0) {
            fragmentGenericCapabilities.put(fragment.bundleID, hostCapabilities);
            if (isResolved())
                fragment.setNewFragmentCapabilities(true);
        }
    }
    if (dynamicAttach) {
        resolver.getResolverExports().put(hostExports.toArray(new ResolverExport[hostExports.size()]));
        resolver.addGenerics(hostCapabilities.toArray(new GenericCapability[hostCapabilities.size()]));
    }
}
Also used : HostSpecification(org.eclipse.osgi.service.resolver.HostSpecification) ExportPackageDescription(org.eclipse.osgi.service.resolver.ExportPackageDescription) ArrayList(java.util.ArrayList) GenericDescription(org.eclipse.osgi.service.resolver.GenericDescription) GenericDescriptionImpl(org.eclipse.osgi.internal.resolver.GenericDescriptionImpl) ExportPackageDescriptionImpl(org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl) GenericSpecification(org.eclipse.osgi.service.resolver.GenericSpecification) BundleSpecification(org.eclipse.osgi.service.resolver.BundleSpecification) VersionConstraint(org.eclipse.osgi.service.resolver.VersionConstraint) ImportPackageSpecification(org.eclipse.osgi.service.resolver.ImportPackageSpecification)

Example 57 with ExportPackageDescription

use of org.eclipse.osgi.service.resolver.ExportPackageDescription in project rt.equinox.framework by eclipse.

the class GroupingChecker method populateRoots.

/*
	 * This method fully populates a bundles package roots for the purpose of resolving
	 * a dynamic import.  Package roots must be fully populated because we need all the
	 * roots to do proper uses constraint verification on a dynamic import supplier.
	 */
public void populateRoots(ResolverBundle bundle) {
    if (bundles.containsKey(bundle))
        // only do the full populate the first time (bug 337272)
        return;
    // process all requires
    BundleConstraint[] requires = bundle.getRequires();
    for (int j = 0; j < requires.length; j++) {
        ResolverBundle selectedSupplier = (ResolverBundle) requires[j].getSelectedSupplier();
        if (selectedSupplier != null)
            isConsistentInternal(bundle, selectedSupplier, new ArrayList<ResolverBundle>(1), true, null);
    }
    // process all imports
    // must check resolved imports to get any dynamically resolved imports
    ExportPackageDescription[] imports = bundle.getBundleDescription().getResolvedImports();
    for (ExportPackageDescription importPkg : imports) {
        List<ResolverExport> exports = bundle.getResolver().getResolverExports().get(importPkg.getName());
        for (ResolverExport export : exports) {
            if (export.getExportPackageDescription() == importPkg)
                isConsistentInternal(bundle, export, true, null);
        }
    }
}
Also used : ExportPackageDescription(org.eclipse.osgi.service.resolver.ExportPackageDescription)

Example 58 with ExportPackageDescription

use of org.eclipse.osgi.service.resolver.ExportPackageDescription in project rt.equinox.framework by eclipse.

the class GroupingChecker method createPackageRoots.

private PackageRoots createPackageRoots(ResolverBundle bundle, String packageName, List<ResolverBundle> visited) {
    if (visited.contains(bundle))
        return null;
    // prevent endless cycles
    visited.add(bundle);
    // check imports
    if (bundle.getBundleDescription().isResolved()) {
        // must check resolved imports to get any dynamically resolved imports
        ExportPackageDescription[] imports = bundle.getBundleDescription().getResolvedImports();
        for (ExportPackageDescription importPkg : imports) {
            if (importPkg.getExporter() == bundle.getBundleDescription() || !importPkg.getName().equals(packageName))
                continue;
            List<ResolverExport> exports = bundle.getResolver().getResolverExports().get(packageName);
            for (ResolverExport export : exports) {
                if (export.getExportPackageDescription() == importPkg)
                    return getPackageRoots(export.getExporter(), packageName, visited);
            }
        }
    } else {
        ResolverImport imported = bundle.getImport(packageName);
        if (imported != null && imported.getSelectedSupplier() != null) {
            // make sure we are not resolved to our own import
            ResolverExport selectedExport = (ResolverExport) imported.getSelectedSupplier();
            if (selectedExport.getExporter() != bundle) {
                // this is all the roots if the package is imported
                return getPackageRoots(selectedExport.getExporter(), packageName, visited);
            }
        }
    }
    // check if the bundle exports the package
    ResolverExport[] exports = bundle.getExports(packageName);
    List<PackageRoots> roots = new ArrayList<>(0);
    // check roots from required bundles
    BundleConstraint[] requires = bundle.getRequires();
    for (int i = 0; i < requires.length; i++) {
        ResolverBundle supplier = (ResolverBundle) requires[i].getSelectedSupplier();
        if (supplier == null)
            // no supplier, probably optional
            continue;
        if (supplier.getExport(packageName) != null) {
            // the required bundle exports the package; get the package roots from it
            PackageRoots requiredRoots = getPackageRoots(supplier, packageName, visited);
            if (requiredRoots != nullPackageRoots)
                roots.add(requiredRoots);
        } else {
            // the bundle does not export the package; but it may reexport another bundle that does
            BundleConstraint[] supplierRequires = supplier.getRequires();
            for (int j = 0; j < supplierRequires.length; j++) {
                ResolverBundle reexported = (ResolverBundle) supplierRequires[j].getSelectedSupplier();
                if (reexported == null || !((BundleSpecification) supplierRequires[j].getVersionConstraint()).isExported())
                    continue;
                if (reexported.getExport(packageName) != null) {
                    // the reexported bundle exports the package; get the package roots from it
                    PackageRoots reExportedRoots = getPackageRoots(reexported, packageName, visited);
                    if (reExportedRoots != nullPackageRoots)
                        roots.add(reExportedRoots);
                }
            }
        }
    }
    if (exports.length > 0 || roots.size() > 1) {
        PackageRoots[] requiredRoots = roots.toArray(new PackageRoots[roots.size()]);
        if (exports.length == 0) {
            PackageRoots superSet = requiredRoots[0];
            for (int i = 1; i < requiredRoots.length; i++) {
                if (requiredRoots[i].superSet(superSet)) {
                    superSet = requiredRoots[i];
                } else if (!superSet.superSet(requiredRoots[i])) {
                    superSet = null;
                    break;
                }
            }
            if (superSet != null)
                return superSet;
        }
        // in this case we cannot share the package roots object; must create one specific for this bundle
        PackageRoots result = new PackageRoots(packageName);
        // first merge all the roots from required bundles
        for (int i = 0; i < requiredRoots.length; i++) result.merge(requiredRoots[i]);
        // always add this bundles exports to the end if it exports the package
        for (int i = 0; i < exports.length; i++) result.addRoot(exports[i]);
        return result;
    }
    return roots.size() == 0 ? nullPackageRoots : roots.get(0);
}
Also used : ExportPackageDescription(org.eclipse.osgi.service.resolver.ExportPackageDescription) BundleSpecification(org.eclipse.osgi.service.resolver.BundleSpecification)

Example 59 with ExportPackageDescription

use of org.eclipse.osgi.service.resolver.ExportPackageDescription in project rt.equinox.framework by eclipse.

the class ResolverImpl method rewireImport.

private void rewireImport(ResolverImport imp, List<ResolverBundle> visited) {
    if (imp.isDynamic() || imp.getSelectedSupplier() != null)
        return;
    // Re-wire 'imp'
    ResolverExport matchingExport = null;
    ExportPackageDescription importSupplier = (ExportPackageDescription) imp.getVersionConstraint().getSupplier();
    ResolverBundle exporter = importSupplier == null ? null : (ResolverBundle) bundleMapping.get(importSupplier.getExporter());
    List<ResolverExport> matches = resolverExports.get(imp.getName());
    for (ResolverExport export : matches) {
        if (export.getExporter() == exporter && importSupplier == export.getExportPackageDescription()) {
            matchingExport = export;
            break;
        }
    }
    imp.addPossibleSupplier(matchingExport);
    // If we still have a null wire and it's not optional, then we have an error
    if (imp.getSelectedSupplier() == null && !imp.isOptional()) {
        // $NON-NLS-1$
        System.err.println("Could not find matching export for " + imp.getVersionConstraint());
    // TODO log error!!
    }
    if (imp.getSelectedSupplier() != null) {
        rewireBundle(((ResolverExport) imp.getSelectedSupplier()).getExporter(), visited);
    }
}
Also used : ExportPackageDescription(org.eclipse.osgi.service.resolver.ExportPackageDescription)

Example 60 with ExportPackageDescription

use of org.eclipse.osgi.service.resolver.ExportPackageDescription in project tycho by eclipse.

the class DependencyComputer method computeBootClasspathExtraAccessRules.

/**
 * Although totally not obvious from the specification text, section 3.15 "Extension Bundles" of
 * OSGi Core Spec apparently says that framework extension bundles can export additional
 * packaged of the underlying JRE. More specific explanation is provided in [1] and I verified
 * that at least Equinox 3.7.1 does indeed behave like described.
 * <p/>
 * There does not seem to be a way to tell which packages exported by a framework extension
 * bundle are supposed to come from JRE and which from the bundle itself, so returned classpath
 * access rules include all packages exported by the framework extension bundles.
 *
 * [1] http://blog.meschberger.ch/2008/10/osgi-bundles-require-classes-from.html
 */
public List<AccessRule> computeBootClasspathExtraAccessRules(StateHelper helper, BundleDescription desc) {
    List<AccessRule> result = new ArrayList<>();
    ExportPackageDescription[] exports = helper.getVisiblePackages(desc);
    for (ExportPackageDescription export : exports) {
        BundleDescription host = export.getExporter();
        BaseDescription fragment = ((ExportPackageDescriptionImpl) export).getFragmentDeclaration();
        if (host.getBundleId() == 0 && fragment != null && isFrameworkExtension(fragment.getSupplier())) {
            result.add(getRule(helper, host, export));
        }
    }
    return result;
}
Also used : BundleDescription(org.eclipse.osgi.service.resolver.BundleDescription) ExportPackageDescription(org.eclipse.osgi.service.resolver.ExportPackageDescription) BaseDescription(org.eclipse.osgi.service.resolver.BaseDescription) ArrayList(java.util.ArrayList) ExportPackageDescriptionImpl(org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl) DefaultAccessRule(org.eclipse.tycho.core.osgitools.DefaultClasspathEntry.DefaultAccessRule) AccessRule(org.eclipse.tycho.classpath.ClasspathEntry.AccessRule)

Aggregations

ExportPackageDescription (org.eclipse.osgi.service.resolver.ExportPackageDescription)61 State (org.eclipse.osgi.service.resolver.State)22 BundleDescription (org.eclipse.osgi.service.resolver.BundleDescription)21 Hashtable (java.util.Hashtable)15 ArrayList (java.util.ArrayList)6 StateObjectFactory (org.eclipse.osgi.service.resolver.StateObjectFactory)6 VersionConstraint (org.eclipse.osgi.service.resolver.VersionConstraint)5 BundleSpecification (org.eclipse.osgi.service.resolver.BundleSpecification)4 ImportPackageSpecification (org.eclipse.osgi.service.resolver.ImportPackageSpecification)4 GenericDescription (org.eclipse.osgi.service.resolver.GenericDescription)3 ExportPackageDescriptionImpl (org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl)2 BaseDescription (org.eclipse.osgi.service.resolver.BaseDescription)2 GenericSpecification (org.eclipse.osgi.service.resolver.GenericSpecification)2 StateWire (org.eclipse.osgi.service.resolver.StateWire)2 AccessRule (org.eclipse.tycho.classpath.ClasspathEntry.AccessRule)2 DefaultAccessRule (org.eclipse.tycho.core.osgitools.DefaultClasspathEntry.DefaultAccessRule)2 Dictionary (java.util.Dictionary)1 HashMap (java.util.HashMap)1 List (java.util.List)1 GenericDescriptionImpl (org.eclipse.osgi.internal.resolver.GenericDescriptionImpl)1