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()]));
}
}
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);
}
}
}
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);
}
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);
}
}
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;
}
Aggregations