use of org.apache.felix.framework.wiring.BundleWireImpl in project felix by apache.
the class ExtensionManager method resolveExtensionBundles.
public List<Bundle> resolveExtensionBundles(Felix felix) {
if (m_unresolvedExtensions.isEmpty()) {
return Collections.emptyList();
}
// Collect the highest version of unresolved that are not already resolved by bsn
List<BundleRevisionImpl> extensions = new ArrayList<BundleRevisionImpl>();
// Collect the unresolved that where filtered out as alternatives in case the highest version doesn't resolve
List<BundleRevisionImpl> alt = new ArrayList<BundleRevisionImpl>();
outer: for (BundleRevisionImpl revision : m_unresolvedExtensions) {
// Already resolved by bsn?
for (BundleRevisionImpl existing : m_resolvedExtensions) {
if (existing.getSymbolicName().equals(revision.getSymbolicName())) {
// Then ignore it
continue outer;
}
}
// Otherwise, does a higher version exist by bsn?
for (BundleRevisionImpl other : m_unresolvedExtensions) {
if ((revision != other) && (revision.getSymbolicName().equals(other.getSymbolicName())) && revision.getVersion().compareTo(other.getVersion()) < 0) {
// Add this one to alternatives and filter it
alt.add(revision);
continue outer;
}
}
// no higher version and not resolved yet by bsn - try to resolve it
extensions.add(revision);
}
// This will return all resolvable revisions with the wires they need
Map<BundleRevisionImpl, List<BundleWire>> wirings = findResolvableExtensions(extensions, alt);
List<Bundle> result = new ArrayList<Bundle>();
for (Map.Entry<BundleRevisionImpl, List<BundleWire>> entry : wirings.entrySet()) {
BundleRevisionImpl revision = entry.getKey();
// move this revision from unresolved to resolved
m_unresolvedExtensions.remove(revision);
m_resolvedExtensions.add(revision);
BundleWire wire = new BundleWireImpl(revision, revision.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE).get(0), m_systemBundleRevision, getCapabilities(BundleRevision.HOST_NAMESPACE).get(0));
try {
revision.resolve(new BundleWiringImpl(m_logger, m_configMap, null, revision, null, Collections.singletonList(wire), Collections.EMPTY_MAP, Collections.EMPTY_MAP));
} catch (Exception ex) {
m_logger.log(revision.getBundle(), Logger.LOG_ERROR, "Error resolving extension bundle : " + revision.getBundle(), ex);
}
felix.getDependencies().addDependent(wire);
appendCapabilities(entry.getKey().getDeclaredExtensionCapabilities(null));
for (BundleWire w : entry.getValue()) {
if (!w.getRequirement().getNamespace().equals(BundleRevision.HOST_NAMESPACE) && !w.getRequirement().getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) {
((BundleWiringImpl) w.getRequirer().getWiring()).addDynamicWire(w);
felix.getDependencies().addDependent(w);
}
}
final File f;
Content revisionContent = revision.getContent();
if (revisionContent instanceof JarContent) {
f = ((JarContent) revisionContent).getFile();
} else {
f = ((DirectoryContent) revisionContent).getFile();
}
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@Override
public Void run() throws Exception {
m_extenderFramework.add(f);
return null;
}
});
} catch (Exception ex) {
m_logger.log(revision.getBundle(), Logger.LOG_ERROR, "Error adding extension bundle to framework classloader: " + revision.getBundle(), ex);
}
felix.setBundleStateAndNotify(revision.getBundle(), Bundle.RESOLVED);
result.add(revision.getBundle());
}
// at this point, all revisions left in unresolved are not resolvable
m_failedExtensions.addAll(m_unresolvedExtensions);
m_unresolvedExtensions.clear();
if (!wirings.isEmpty()) {
felix.getResolver().addRevision(getRevision());
}
return result;
}
use of org.apache.felix.framework.wiring.BundleWireImpl in project felix by apache.
the class StatefulResolver method markResolvedRevisions.
private void markResolvedRevisions(Map<Resource, List<Wire>> wireMap) throws ResolveException {
boolean debugLog = m_felix.getLogger().getLogLevel() >= Logger.LOG_DEBUG;
// First pass.
if (wireMap != null) {
// First pass: Loop through the wire map to find the host wires
// for any fragments and map a host to all of its fragments.
Map<Resource, List<BundleRevision>> hosts = new HashMap<Resource, List<BundleRevision>>();
for (Entry<Resource, List<Wire>> entry : wireMap.entrySet()) {
Resource revision = entry.getKey();
List<Wire> wires = entry.getValue();
if (Util.isFragment(revision)) {
for (Wire w : wires) {
List<BundleRevision> fragments = hosts.get(w.getProvider());
if (fragments == null) {
fragments = new ArrayList<BundleRevision>();
hosts.put(w.getProvider(), fragments);
}
if (w.getRequirer() instanceof BundleRevision)
fragments.add((BundleRevision) w.getRequirer());
}
}
}
// Second pass: Loop through the wire map to do three things:
// 1) convert resolver wires to bundle wires 2) create wiring
// objects for revisions and 3) record dependencies among
// revisions. We don't actually set the wirings here because
// that indicates that a revision is resolved and we don't want
// to mark anything as resolved unless we succussfully create
// all wirings.
Map<BundleRevision, BundleWiringImpl> wirings = new HashMap<BundleRevision, BundleWiringImpl>(wireMap.size());
for (Entry<Resource, List<Wire>> entry : wireMap.entrySet()) {
Resource resource = entry.getKey();
if (!(resource instanceof BundleRevision))
continue;
BundleRevision revision = (BundleRevision) resource;
List<Wire> resolverWires = entry.getValue();
List<BundleWire> bundleWires = new ArrayList<BundleWire>(resolverWires.size());
// the new ones.
if ((revision.getWiring() != null) && Util.isFragment(revision)) {
// Fragments only have host wires, so just add them all.
bundleWires.addAll(revision.getWiring().getRequiredWires(null));
}
// Loop through resolver wires to calculate the package
// space implied by the wires as well as to record the
// dependencies.
Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();
for (Wire rw : resolverWires) {
// TODO can we optimize this?
if (!(rw.getRequirer() instanceof BundleRevision))
continue;
BundleRevision requirer = (BundleRevision) rw.getRequirer();
if (!(rw.getRequirement() instanceof BundleRequirement))
continue;
BundleRequirement requirement = (BundleRequirement) rw.getRequirement();
if (!(rw.getProvider() instanceof BundleRevision))
continue;
BundleRevision provider = (BundleRevision) rw.getProvider();
if (!(rw.getCapability() instanceof BundleCapability))
continue;
BundleCapability capability = (BundleCapability) rw.getCapability();
BundleWire bw = new BundleWireImpl(requirer, requirement, provider, capability);
bundleWires.add(bw);
if (Util.isFragment(revision)) {
if (debugLog) {
m_felix.getLogger().log(Logger.LOG_DEBUG, "FRAGMENT WIRE: " + rw.toString());
}
} else {
if (debugLog) {
m_felix.getLogger().log(Logger.LOG_DEBUG, "WIRE: " + rw.toString());
}
if (capability.getNamespace().equals(BundleRevision.PACKAGE_NAMESPACE)) {
importedPkgs.put((String) capability.getAttributes().get(BundleRevision.PACKAGE_NAMESPACE), provider);
} else if (capability.getNamespace().equals(BundleRevision.BUNDLE_NAMESPACE)) {
Set<String> pkgs = calculateExportedAndReexportedPackages(provider, wireMap, new HashSet<String>(), new HashSet<BundleRevision>());
for (String pkg : pkgs) {
List<BundleRevision> revs = requiredPkgs.get(pkg);
if (revs == null) {
revs = new ArrayList<BundleRevision>();
requiredPkgs.put(pkg, revs);
}
revs.add(provider);
}
}
}
}
List<BundleRevision> fragments = hosts.get(revision);
try {
wirings.put(revision, new BundleWiringImpl(m_felix.getLogger(), m_felix.getConfig(), this, (BundleRevisionImpl) revision, fragments, bundleWires, importedPkgs, requiredPkgs));
} catch (Exception ex) {
// throw an exception.
for (Entry<BundleRevision, BundleWiringImpl> wiringEntry : wirings.entrySet()) {
// Dispose of wiring.
try {
wiringEntry.getValue().dispose();
} catch (Exception ex2) {
// We are in big trouble.
RuntimeException rte = new RuntimeException("Unable to clean up resolver failure.", ex2);
m_felix.getLogger().log(Logger.LOG_ERROR, rte.getMessage(), ex2);
throw rte;
}
}
ResolveException re = new ResolveException("Unable to resolve " + revision, revision, null);
re.initCause(ex);
m_felix.getLogger().log(Logger.LOG_ERROR, re.getMessage(), ex);
throw re;
}
}
// and update the resolver state.
for (Entry<BundleRevision, BundleWiringImpl> entry : wirings.entrySet()) {
BundleRevisionImpl revision = (BundleRevisionImpl) entry.getKey();
// Mark revision as resolved.
BundleWiring wiring = entry.getValue();
revision.resolve(entry.getValue());
// Record dependencies.
for (BundleWire bw : wiring.getRequiredWires(null)) {
m_felix.getDependencies().addDependent(bw);
}
// Reindex the revision's capabilities since its resolved
// capabilities could be different than its declared ones
// (e.g., due to substitutable exports).
addRevision(revision);
// Update the state of the revision's bundle to resolved as well.
markBundleResolved(revision);
}
}
}
use of org.apache.felix.framework.wiring.BundleWireImpl in project felix by apache.
the class StatefulResolver method resolve.
BundleRevision resolve(BundleRevision revision, String pkgName) throws ResolutionException, BundleException {
BundleRevision provider = null;
// acquired the global lock below.
if ((revision.getWiring() != null) && isAllowedDynamicImport(revision, pkgName)) {
// Acquire global lock.
boolean locked = m_felix.acquireGlobalLock();
if (!locked) {
throw new ResolveException("Unable to acquire global lock for resolve.", revision, null);
}
// the case if a resolver hook does something bad.
if (m_isResolving) {
m_felix.releaseGlobalLock();
throw new IllegalStateException("Nested resolve operations not allowed.");
}
m_isResolving = true;
Map<Resource, List<Wire>> wireMap = null;
try {
// Double check to make sure that someone hasn't beaten us to
// dynamically importing the package, which can happen if two
// threads are racing to do so. If we have an existing wire,
// then just return it instead.
provider = ((BundleWiringImpl) revision.getWiring()).getImportedPackageSource(pkgName);
if (provider == null) {
// Prepare resolver hooks, if any.
ResolverHookRecord record = prepareResolverHooks(Collections.singleton(revision), Collections.EMPTY_SET);
// Select any singletons in the resolver state.
selectSingletons(record);
// Catch any resolve exception to rethrow later because
// we may need to call end() on resolver hooks.
ResolutionException rethrow = null;
try {
List<BundleRequirement> dynamics = Util.getDynamicRequirements(revision.getWiring().getRequirements(null));
// Loop through the importer's dynamic requirements to determine if
// there is a matching one for the package from which we want to
// load a class.
Map<String, Object> attrs = Collections.singletonMap(BundleRevision.PACKAGE_NAMESPACE, (Object) pkgName);
BundleRequirementImpl req = new BundleRequirementImpl(revision, BundleRevision.PACKAGE_NAMESPACE, Collections.EMPTY_MAP, attrs);
final List<BundleCapability> candidates = findProvidersInternal(record, req, false, true);
// Try to find a dynamic requirement that matches the capabilities.
BundleRequirementImpl dynReq = null;
for (int dynIdx = 0; (candidates.size() > 0) && (dynReq == null) && (dynIdx < dynamics.size()); dynIdx++) {
for (Iterator<BundleCapability> itCand = candidates.iterator(); (dynReq == null) && itCand.hasNext(); ) {
Capability cap = itCand.next();
if (CapabilitySet.matches(cap, ((BundleRequirementImpl) dynamics.get(dynIdx)).getFilter())) {
dynReq = (BundleRequirementImpl) dynamics.get(dynIdx);
}
}
}
// any candidates that do not match it.
if (dynReq != null) {
for (Iterator<BundleCapability> itCand = candidates.iterator(); itCand.hasNext(); ) {
Capability cap = itCand.next();
if (!CapabilitySet.matches(cap, dynReq.getFilter())) {
itCand.remove();
}
}
} else {
candidates.clear();
}
Map<Resource, Wiring> wirings = getWirings();
wireMap = wirings.containsKey(revision) ? m_resolver.resolveDynamic(new ResolveContextImpl(this, wirings, record, Collections.<BundleRevision>emptyList(), Collections.<BundleRevision>emptyList(), getFragments()) {
@Override
public List<Capability> findProviders(Requirement br) {
return (List) candidates;
}
}, revision.getWiring(), dynReq) : Collections.<Resource, List<Wire>>emptyMap();
} catch (ResolutionException ex) {
rethrow = ex;
}
// Release resolver hooks, if any.
releaseResolverHooks(record);
// If the resolve failed, rethrow the exception.
if (rethrow != null) {
throw rethrow;
}
if ((wireMap != null) && wireMap.containsKey(revision)) {
List<Wire> dynamicWires = wireMap.remove(revision);
Wire dynamicWire = dynamicWires.get(0);
// Mark all revisions as resolved.
markResolvedRevisions(wireMap);
// Dynamically add new wire to importing revision.
if (dynamicWire != null) {
// TODO can we optimize this?
if (dynamicWire.getRequirer() instanceof BundleRevision && dynamicWire.getRequirement() instanceof BundleRequirement && dynamicWire.getProvider() instanceof BundleRevision && dynamicWire.getCapability() instanceof BundleCapability) {
BundleRevision dwRequirer = (BundleRevision) dynamicWire.getRequirer();
BundleRequirement dwRequirement = (BundleRequirement) dynamicWire.getRequirement();
BundleRevision dwProvider = (BundleRevision) dynamicWire.getProvider();
BundleCapability dwCapability = (BundleCapability) dynamicWire.getCapability();
BundleWire bw = new BundleWireImpl(dwRequirer, dwRequirement, dwProvider, dwCapability);
m_felix.getDependencies().addDependent(bw);
((BundleWiringImpl) revision.getWiring()).addDynamicWire(bw);
m_felix.getLogger().log(Logger.LOG_DEBUG, "DYNAMIC WIRE: " + dynamicWire);
provider = ((BundleWiringImpl) revision.getWiring()).getImportedPackageSource(pkgName);
}
}
}
}
} finally {
// Clear resolving flag.
m_isResolving = false;
// Always release the global lock.
m_felix.releaseGlobalLock();
}
fireResolvedEvents(wireMap);
}
return provider;
}
Aggregations