use of org.osgi.framework.wiring.BundleCapability in project felix by apache.
the class Util method getCapabilityByNamespace.
/**
* Returns all the capabilities from a module that has a specified namespace.
*
* @param br module providing capabilities
* @param namespace capability namespace
* @return array of matching capabilities or empty if none found
*/
public static List<BundleCapability> getCapabilityByNamespace(BundleRevision br, String namespace) {
final List<BundleCapability> matching = new ArrayList();
final List<BundleCapability> caps = (br.getWiring() != null) ? br.getWiring().getCapabilities(null) : br.getDeclaredCapabilities(null);
if (caps != null) {
for (BundleCapability cap : caps) {
if (cap.getNamespace().equals(namespace)) {
matching.add(cap);
}
}
}
return matching;
}
use of org.osgi.framework.wiring.BundleCapability in project felix by apache.
the class BundleRevisionDependencies method getImportingBundles.
public synchronized Set<Bundle> getImportingBundles(Bundle exporter, BundleCapability exportCap) {
// Create set for storing importing bundles.
Set<Bundle> result = new HashSet<Bundle>();
// Get exported package name.
String pkgName = (String) exportCap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE);
// The spec says that require-bundle should be returned with importers.
for (BundleRevision revision : exporter.adapt(BundleRevisions.class).getRevisions()) {
Map<BundleCapability, Set<BundleWire>> caps = m_dependentsMap.get(revision);
if (caps != null) {
for (Entry<BundleCapability, Set<BundleWire>> entry : caps.entrySet()) {
BundleCapability cap = entry.getKey();
if ((cap.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) && cap.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(pkgName)) || cap.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE)) {
for (BundleWire dependentWire : entry.getValue()) {
result.add(dependentWire.getRequirer().getBundle());
}
}
}
}
}
// Return the results.
return result;
}
use of org.osgi.framework.wiring.BundleCapability in project felix by apache.
the class BundleRevisionDependencies method getDependentBundles.
public synchronized Set<Bundle> getDependentBundles(Bundle bundle) {
Set<Bundle> result = new HashSet<Bundle>();
List<BundleRevision> revisions = bundle.adapt(BundleRevisions.class).getRevisions();
for (BundleRevision revision : revisions) {
// since their dependents are their hosts.
if (Util.isFragment(revision)) {
BundleWiring wiring = revision.getWiring();
if (wiring != null) {
for (BundleWire bw : wiring.getRequiredWires(null)) {
if (HostNamespace.HOST_NAMESPACE.equals(bw.getCapability().getNamespace())) {
result.add(bw.getProvider().getBundle());
}
}
}
} else {
Map<BundleCapability, Set<BundleWire>> caps = m_dependentsMap.get(revision);
if (caps != null) {
for (Entry<BundleCapability, Set<BundleWire>> entry : caps.entrySet()) {
for (BundleWire dependentWire : entry.getValue()) {
result.add(dependentWire.getRequirer().getBundle());
}
}
}
}
}
return result;
}
use of org.osgi.framework.wiring.BundleCapability in project felix by apache.
the class BundleWiringImpl method listResourcesInternal.
private Collection<ResourceSource> listResourcesInternal(String path, List<String> pattern, int options) {
if (isInUse()) {
boolean recurse = (options & BundleWiring.LISTRESOURCES_RECURSE) > 0;
boolean localOnly = (options & BundleWiring.LISTRESOURCES_LOCAL) > 0;
// Check for cycles, which can happen with Require-Bundle.
Set<String> cycles = (Set<String>) m_listResourcesCycleCheck.get();
if (cycles == null) {
cycles = new HashSet<String>();
m_listResourcesCycleCheck.set(cycles);
}
if (cycles.contains(path)) {
return Collections.EMPTY_LIST;
}
cycles.add(path);
try {
// Calculate set of remote resources (i.e., those either
// imported or required).
Collection<ResourceSource> remoteResources = new TreeSet<ResourceSource>();
// Imported packages cannot have merged content, so we need to
// keep track of these packages.
Set<String> noMerging = new HashSet<String>();
// Loop through wires to compute remote resources.
for (BundleWire bw : m_wires) {
if (bw.getCapability().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) {
// For imported packages, we only need to calculate
// the remote resources of the specific imported package.
remoteResources.addAll(calculateRemotePackageResources(bw, bw.getCapability(), recurse, path, pattern, noMerging));
} else if (bw.getCapability().getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE)) {
// For required bundles, all declared package capabilities
// from the required bundle will be available to requirers,
// so get the target required bundle's declared packages
// and handle them in a similar fashion to a normal import
// except that their content can be merged with local
// packages.
List<BundleCapability> exports = bw.getProviderWiring().getRevision().getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
for (BundleCapability export : exports) {
remoteResources.addAll(calculateRemotePackageResources(bw, export, recurse, path, pattern, null));
}
// Since required bundle may reexport bundles it requires,
// check its wires for this case.
List<BundleWire> requiredBundles = bw.getProviderWiring().getRequiredWires(BundleRevision.BUNDLE_NAMESPACE);
for (BundleWire rbWire : requiredBundles) {
String visibility = rbWire.getRequirement().getDirectives().get(Constants.VISIBILITY_DIRECTIVE);
if ((visibility != null) && (visibility.equals(Constants.VISIBILITY_REEXPORT))) {
// For each reexported required bundle, treat them
// in a similar fashion as a normal required bundle
// by including all of their declared package
// capabilities in the requiring bundle's class
// space.
List<BundleCapability> reexports = rbWire.getProviderWiring().getRevision().getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
for (BundleCapability reexport : reexports) {
remoteResources.addAll(calculateRemotePackageResources(bw, reexport, recurse, path, pattern, null));
}
}
}
}
}
// Calculate set of local resources (i.e., those contained
// in the revision or its fragments).
Collection<ResourceSource> localResources = new TreeSet<ResourceSource>();
// Get the revision's content path, which includes contents
// from fragments.
List<Content> contentPath = m_revision.getContentPath();
for (Content content : contentPath) {
Enumeration<String> e = content.getEntries();
if (e != null) {
while (e.hasMoreElements()) {
String resource = e.nextElement();
String resourcePath = getTrailingPath(resource);
if (!noMerging.contains(resourcePath)) {
if ((!recurse && resourcePath.equals(path)) || (recurse && resourcePath.startsWith(path))) {
if (matchesPattern(pattern, getPathHead(resource))) {
localResources.add(new ResourceSource(resource, m_revision));
}
}
}
}
}
}
if (localOnly) {
return localResources;
} else {
remoteResources.addAll(localResources);
return remoteResources;
}
} finally {
cycles.remove(path);
if (cycles.isEmpty()) {
m_listResourcesCycleCheck.set(null);
}
}
}
return null;
}
use of org.osgi.framework.wiring.BundleCapability in project felix by apache.
the class BundleWiringImpl method diagnoseClassLoadError.
private static String diagnoseClassLoadError(StatefulResolver resolver, BundleRevision revision, String name) {
// We will try to do some diagnostics here to help the developer
// deal with this exception.
// Get package name.
String pkgName = Util.getClassPackage(name);
if (pkgName.length() == 0) {
return null;
}
// First, get the bundle string of the revision doing the class loader.
String importer = revision.getBundle().toString();
// Next, check to see if the revision imports the package.
List<BundleWire> wires = (revision.getWiring() == null) ? null : revision.getWiring().getProvidedWires(null);
for (int i = 0; (wires != null) && (i < wires.size()); i++) {
if (wires.get(i).getCapability().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE) && wires.get(i).getCapability().getAttributes().get(BundleRevision.PACKAGE_NAMESPACE).equals(pkgName)) {
String exporter = wires.get(i).getProviderWiring().getBundle().toString();
StringBuffer sb = new StringBuffer("*** Package '");
sb.append(pkgName);
sb.append("' is imported by bundle ");
sb.append(importer);
sb.append(" from bundle ");
sb.append(exporter);
sb.append(", but the exported package from bundle ");
sb.append(exporter);
sb.append(" does not contain the requested class '");
sb.append(name);
sb.append("'. Please verify that the class name is correct in the importing bundle ");
sb.append(importer);
sb.append(" and/or that the exported package is correctly bundled in ");
sb.append(exporter);
sb.append(". ***");
return sb.toString();
}
}
// Next, check to see if the package was optionally imported and
// whether or not there is an exporter available.
List<BundleRequirement> reqs = revision.getWiring().getRequirements(null);
// Next, check to see if the package is dynamically imported by the revision.
if (resolver.isAllowedDynamicImport(revision, pkgName)) {
// Try to see if there is an exporter available.
Map<String, String> dirs = Collections.EMPTY_MAP;
Map<String, Object> attrs = Collections.singletonMap(BundleRevision.PACKAGE_NAMESPACE, (Object) pkgName);
BundleRequirementImpl req = new BundleRequirementImpl(revision, BundleRevision.PACKAGE_NAMESPACE, dirs, attrs);
List<BundleCapability> exporters = resolver.findProviders(req, false);
BundleRevision provider = null;
try {
provider = resolver.resolve(revision, pkgName);
} catch (Exception ex) {
provider = null;
}
String exporter = (exporters.isEmpty()) ? null : exporters.iterator().next().toString();
StringBuffer sb = new StringBuffer("*** Class '");
sb.append(name);
sb.append("' was not found, but this is likely normal since package '");
sb.append(pkgName);
sb.append("' is dynamically imported by bundle ");
sb.append(importer);
sb.append(".");
if ((exporters.size() > 0) && (provider == null)) {
sb.append(" However, bundle ");
sb.append(exporter);
sb.append(" does export this package with attributes that do not match.");
}
sb.append(" ***");
return sb.toString();
}
// Next, check to see if there are any exporters for the package at all.
Map<String, String> dirs = Collections.EMPTY_MAP;
Map<String, Object> attrs = Collections.singletonMap(BundleRevision.PACKAGE_NAMESPACE, (Object) pkgName);
BundleRequirementImpl req = new BundleRequirementImpl(revision, BundleRevision.PACKAGE_NAMESPACE, dirs, attrs);
List<BundleCapability> exports = resolver.findProviders(req, false);
if (exports.size() > 0) {
boolean classpath = false;
try {
BundleRevisionImpl.getSecureAction().getClassLoader(BundleClassLoader.class).loadClass(name);
classpath = true;
} catch (NoClassDefFoundError err) {
// Ignore
} catch (Exception ex) {
// Ignore
}
String exporter = exports.iterator().next().toString();
StringBuffer sb = new StringBuffer("*** Class '");
sb.append(name);
sb.append("' was not found because bundle ");
sb.append(importer);
sb.append(" does not import '");
sb.append(pkgName);
sb.append("' even though bundle ");
sb.append(exporter);
sb.append(" does export it.");
if (classpath) {
sb.append(" Additionally, the class is also available from the system class loader. There are two fixes: 1) Add an import for '");
sb.append(pkgName);
sb.append("' to bundle ");
sb.append(importer);
sb.append("; imports are necessary for each class directly touched by bundle code or indirectly touched, such as super classes if their methods are used. ");
sb.append("2) Add package '");
sb.append(pkgName);
sb.append("' to the '");
sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
} else {
sb.append(" To resolve this issue, add an import for '");
sb.append(pkgName);
sb.append("' to bundle ");
sb.append(importer);
sb.append(".");
}
sb.append(" ***");
return sb.toString();
}
// class loader.
try {
BundleRevisionImpl.getSecureAction().getClassLoader(BundleClassLoader.class).loadClass(name);
StringBuffer sb = new StringBuffer("*** Package '");
sb.append(pkgName);
sb.append("' is not imported by bundle ");
sb.append(importer);
sb.append(", nor is there any bundle that exports package '");
sb.append(pkgName);
sb.append("'. However, the class '");
sb.append(name);
sb.append("' is available from the system class loader. There are two fixes: 1) Add package '");
sb.append(pkgName);
sb.append("' to the '");
sb.append(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA);
sb.append("' property and modify bundle ");
sb.append(importer);
sb.append(" to import this package; this causes the system bundle to export class path packages. 2) Add package '");
sb.append(pkgName);
sb.append("' to the '");
sb.append(Constants.FRAMEWORK_BOOTDELEGATION);
sb.append("' property; a library or VM bug can cause classes to be loaded by the wrong class loader. The first approach is preferable for preserving modularity.");
sb.append(" ***");
return sb.toString();
} catch (Exception ex2) {
}
// Finally, if there are no imports or exports for the package
// and it is not available on the system class path, simply
// log a message saying so.
StringBuffer sb = new StringBuffer("*** Class '");
sb.append(name);
sb.append("' was not found. Bundle ");
sb.append(importer);
sb.append(" does not import package '");
sb.append(pkgName);
sb.append("', nor is the package exported by any other bundle or available from the system class loader.");
sb.append(" ***");
return sb.toString();
}
Aggregations