use of org.apache.felix.framework.util.ShrinkableCollection in project felix by apache.
the class StatefulResolver method findProvidersInternal.
synchronized List<BundleCapability> findProvidersInternal(final ResolverHookRecord record, final Requirement req, final boolean obeyMandatory, final boolean invokeHooksAndSecurity) {
List<BundleCapability> result = new ArrayList<BundleCapability>();
CapabilitySet capSet = m_capSets.get(req.getNamespace());
if (capSet != null) {
// Get the requirement's filter; if this is our own impl we
// have a shortcut to get the already parsed filter, otherwise
// we must parse it from the directive.
SimpleFilter sf;
if (req instanceof BundleRequirementImpl) {
sf = ((BundleRequirementImpl) req).getFilter();
} else {
String filter = req.getDirectives().get(Constants.FILTER_DIRECTIVE);
if (filter == null) {
sf = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
} else {
sf = SimpleFilter.parse(filter);
}
}
// Find the matching candidates.
Set<Capability> matches = capSet.match(sf, obeyMandatory);
// Filter matching candidates.
for (Capability cap : matches) {
if (!(cap instanceof BundleCapability))
continue;
BundleCapability bcap = (BundleCapability) cap;
// Filter according to security.
if (invokeHooksAndSecurity && filteredBySecurity((BundleRequirement) req, bcap)) {
continue;
}
// dynamic attachment of fragments.
if (req.getNamespace().equals(BundleRevision.HOST_NAMESPACE) && (bcap.getRevision().getWiring() != null)) {
continue;
}
result.add(bcap);
}
}
if (invokeHooksAndSecurity) {
// based on a whitelist and/or fine-grained candidate filtering.
if (!result.isEmpty() && !record.getResolverHookRefs().isEmpty()) {
// from disallowed revisions.
if (record.getBundleRevisionWhitelist() != null) {
for (Iterator<BundleCapability> it = result.iterator(); it.hasNext(); ) {
if (!record.getBundleRevisionWhitelist().contains(it.next().getRevision())) {
it.remove();
}
}
}
// Now give the hooks a chance to do fine-grained filtering.
ShrinkableCollection<BundleCapability> shrinkable = new ShrinkableCollection<BundleCapability>(result);
for (ResolverHook hook : record.getResolverHooks()) {
try {
Felix.m_secureAction.invokeResolverHookMatches(hook, (BundleRequirement) req, shrinkable);
} catch (Throwable th) {
m_logger.log(Logger.LOG_WARNING, "Resolver hook exception.", th);
}
}
}
}
Collections.sort(result, new CandidateComparator());
return result;
}
use of org.apache.felix.framework.util.ShrinkableCollection in project felix by apache.
the class Felix method getServiceReferences.
/**
* Retrieves an array of {@link ServiceReference} objects based on calling bundle,
* service class name, and filter expression. Optionally checks for isAssignable to
* make sure that the service can be cast to the
* @param bundle Calling Bundle
* @param className Service Classname or <code>null</code> for all
* @param expr Filter Criteria or <code>null</code>
* @return Array of ServiceReference objects that meet the criteria
* @throws InvalidSyntaxException
*/
ServiceReference[] getServiceReferences(final BundleImpl bundle, final String className, final String expr, final boolean checkAssignable) throws InvalidSyntaxException {
// Define filter if expression is not null.
SimpleFilter filter = null;
if (expr != null) {
try {
filter = SimpleFilter.parse(expr);
} catch (Exception ex) {
throw new InvalidSyntaxException(ex.getMessage(), expr);
}
}
// Ask the service registry for all matching service references.
final Collection refList = m_registry.getServiceReferences(className, filter);
// Filter on assignable references
if (checkAssignable) {
for (Iterator refIter = refList.iterator(); refIter.hasNext(); ) {
// Get the current service reference.
ServiceReference ref = (ServiceReference) refIter.next();
// Now check for castability.
if (!Util.isServiceAssignable(bundle, ref)) {
refIter.remove();
}
}
}
// If the requesting bundle is the system bundle, ignore the effects of the findhooks
Collection resRefList = (bundle == this ? new ArrayList(refList) : refList);
// activate findhooks
Set<ServiceReference<org.osgi.framework.hooks.service.FindHook>> findHooks = getHookRegistry().getHooks(org.osgi.framework.hooks.service.FindHook.class);
for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks) {
org.osgi.framework.hooks.service.FindHook fh = getService(this, sr, false);
if (fh != null) {
try {
m_secureAction.invokeServiceFindHook(fh, bundle._getBundleContext(), className, expr, !checkAssignable, new ShrinkableCollection(refList));
} catch (Throwable th) {
m_logger.log(sr, Logger.LOG_WARNING, "Problem invoking service registry hook", th);
} finally {
m_registry.ungetService(this, sr, null);
}
}
}
// the requestor, resRefList is a copy of the original list before the hooks were invoked.
if (resRefList.size() > 0) {
return (ServiceReference[]) resRefList.toArray(new ServiceReference[resRefList.size()]);
}
return null;
}
use of org.apache.felix.framework.util.ShrinkableCollection in project felix by apache.
the class StatefulResolver method selectSingletonsUsingHooks.
/*
* Groups singletons based on resolver hook filtering and then selects
* the singleton from each group with the highest version that is in
* the resolver hook whitelist. No selection is made if a group already
* has a resolved singleton in it.
*/
private void selectSingletonsUsingHooks(ResolverHookRecord record) throws BundleException {
// Convert singleton bundle revision map into a map using
// bundle capabilities instead, since this is what the resolver
// hooks require.
Map<BundleCapability, Collection<BundleCapability>> allCollisions = new HashMap<BundleCapability, Collection<BundleCapability>>();
for (Entry<String, List<BundleRevision>> entry : m_singletons.entrySet()) {
Collection<BundleCapability> bundleCaps = new ArrayList<BundleCapability>();
for (BundleRevision br : entry.getValue()) {
List<BundleCapability> caps = br.getDeclaredCapabilities(BundleRevision.BUNDLE_NAMESPACE);
if (!caps.isEmpty()) {
bundleCaps.add(caps.get(0));
}
}
for (BundleCapability bc : bundleCaps) {
Collection<BundleCapability> capCopy = new ShrinkableCollection<BundleCapability>(new ArrayList<BundleCapability>(bundleCaps));
capCopy.remove(bc);
allCollisions.put(bc, capCopy);
}
}
// Invoke hooks to allow them to filter singleton collisions.
for (ResolverHook hook : record.getResolverHooks()) {
for (Entry<BundleCapability, Collection<BundleCapability>> entry : allCollisions.entrySet()) {
try {
Felix.m_secureAction.invokeResolverHookSingleton(hook, entry.getKey(), entry.getValue());
} catch (Throwable ex) {
throw new BundleException("Resolver hook exception: " + ex.getMessage(), BundleException.REJECTED_BY_HOOK, ex);
}
}
}
// Create groups according to how the resolver hooks filtered the
// collisions.
List<List<BundleRevision>> groups = new ArrayList<List<BundleRevision>>();
while (!allCollisions.isEmpty()) {
BundleCapability target = allCollisions.entrySet().iterator().next().getKey();
groups.add(groupSingletons(allCollisions, target, new ArrayList<BundleRevision>()));
}
// Now select the singletons available for this resolve operation.
for (List<BundleRevision> group : groups) {
selectSingleton(record, group);
}
}
use of org.apache.felix.framework.util.ShrinkableCollection in project felix by apache.
the class BundleImpl method createRevision.
private BundleRevisionImpl createRevision(boolean isUpdate) throws Exception {
// Get and parse the manifest from the most recent revision and
// create an associated revision object for it.
Map headerMap = Util.getMultiReleaseAwareManifestHeaders(getFramework()._getProperty("java.specification.version"), m_archive.getCurrentRevision());
// Create the bundle revision instance.
BundleRevisionImpl revision = new BundleRevisionImpl(this, Long.toString(getBundleId()) + "." + m_archive.getCurrentRevisionNumber().toString(), headerMap, m_archive.getCurrentRevision().getContent());
// For R4 bundles, verify that the bundle symbolic name + version
// is unique unless this check has been disabled.
String allowMultiple = (String) getFramework().getConfig().get(Constants.FRAMEWORK_BSNVERSION);
allowMultiple = (allowMultiple == null) ? Constants.FRAMEWORK_BSNVERSION_MANAGED : allowMultiple;
if (revision.getManifestVersion().equals("2") && !allowMultiple.equals(Constants.FRAMEWORK_BSNVERSION_MULTIPLE)) {
Version bundleVersion = revision.getVersion();
bundleVersion = (bundleVersion == null) ? Version.emptyVersion : bundleVersion;
String symName = revision.getSymbolicName();
List<Bundle> collisionCanditates = new ArrayList<Bundle>();
Bundle[] bundles = getFramework().getBundles();
for (int i = 0; (bundles != null) && (i < bundles.length); i++) {
long id = ((BundleImpl) bundles[i]).getBundleId();
if (id != getBundleId()) {
if (symName.equals(bundles[i].getSymbolicName()) && bundleVersion.equals(bundles[i].getVersion())) {
collisionCanditates.add(bundles[i]);
}
}
}
if (!collisionCanditates.isEmpty() && allowMultiple.equals(Constants.FRAMEWORK_BSNVERSION_MANAGED)) {
Set<ServiceReference<CollisionHook>> hooks = getFramework().getHookRegistry().getHooks(CollisionHook.class);
if (!hooks.isEmpty()) {
Collection<Bundle> shrinkableCollisionCandidates = new ShrinkableCollection<Bundle>(collisionCanditates);
for (ServiceReference<CollisionHook> hook : hooks) {
CollisionHook ch = getFramework().getService(getFramework(), hook, false);
if (ch != null) {
int operationType;
Bundle target;
if (isUpdate) {
operationType = CollisionHook.UPDATING;
target = this;
} else {
operationType = CollisionHook.INSTALLING;
target = m_installingBundle == null ? this : m_installingBundle;
}
Felix.m_secureAction.invokeBundleCollisionHook(ch, operationType, target, shrinkableCollisionCandidates);
}
}
}
}
if (!collisionCanditates.isEmpty()) {
throw new BundleException("Bundle symbolic name and version are not unique: " + symName + ':' + bundleVersion, BundleException.DUPLICATE_BUNDLE_ERROR);
}
}
return revision;
}
Aggregations