blob: 7e1e863fd68881bd51b0a7cc7ca861c0bc8352c9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 2016 VMware Inc and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* VMware Inc. - initial contribution
* IBM - bug fixes and enhancements
*******************************************************************************/
package org.eclipse.equinox.internal.region;
import java.util.*;
import org.eclipse.equinox.region.RegionFilter;
import org.osgi.framework.*;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
public final class StandardRegionFilter implements RegionFilter {
final static Filter ALL;
static {
try {
ALL = FrameworkUtil.createFilter("(|(!(all=*))(all=*))"); //$NON-NLS-1$
} catch (InvalidSyntaxException e) {
// should never happen!
e.printStackTrace();
throw new RuntimeException(e);
}
}
private static final String BUNDLE_ID_ATTR = "id"; //$NON-NLS-1$
private final Map<String, Collection<Filter>> filters;
public StandardRegionFilter(Map<String, Collection<Filter>> filters) {
if (filters == null) {
throw new IllegalArgumentException("filters must not be null."); //$NON-NLS-1$
}
// must perform deep copy to avoid external changes
this.filters = new HashMap<String, Collection<Filter>>((int) ((filters.size() / 0.75) + 1));
for (Map.Entry<String, Collection<Filter>> namespace : filters.entrySet()) {
Collection<Filter> namespaceFilters = new ArrayList<Filter>(namespace.getValue());
this.filters.put(namespace.getKey(), namespaceFilters);
}
}
public boolean isAllowed(Bundle bundle) {
if (bundle == null) {
return false;
}
HashMap<String, Object> attrs = new HashMap<String, Object>(4);
String bsn = bundle.getSymbolicName();
if (bsn != null) {
attrs.put(VISIBLE_BUNDLE_NAMESPACE, bsn);
attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
}
attrs.put(org.osgi.framework.Constants.BUNDLE_VERSION_ATTRIBUTE, bundle.getVersion());
attrs.put(BUNDLE_ID_ATTR, bundle.getBundleId());
return isBundleAllowed(attrs);
}
public boolean isAllowed(BundleRevision bundle) {
HashMap<String, Object> attrs = new HashMap<String, Object>(4);
String bsn = bundle.getSymbolicName();
if (bsn != null) {
attrs.put(VISIBLE_BUNDLE_NAMESPACE, bsn);
attrs.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, bsn);
}
attrs.put(org.osgi.framework.Constants.BUNDLE_VERSION_ATTRIBUTE, bundle.getVersion());
attrs.put(BUNDLE_ID_ATTR, getBundleId(bundle));
return isBundleAllowed(attrs);
}
/**
* Determines whether this filter allows the bundle with the given attributes
*
* @param bundleAttributes the bundle attributes
* @return <code>true</code> if the bundle is allowed and <code>false</code>otherwise
*/
private boolean isBundleAllowed(Map<String, ?> bundleAttributes) {
return isAllowed(VISIBLE_BUNDLE_NAMESPACE, bundleAttributes);
}
private static boolean match(Collection<Filter> filters, Map<String, ?> attrs) {
if (filters == null)
return false;
for (Filter filter : filters) {
if (filter == ALL || filter.matches(attrs))
return true;
}
return false;
}
private static boolean match(Collection<Filter> filters, ServiceReference<?> service) {
if (filters == null)
return false;
for (Filter filter : filters) {
if (filter == ALL || filter.match(service))
return true;
}
return false;
}
public boolean isAllowed(ServiceReference<?> service) {
if (match(filters.get(VISIBLE_OSGI_SERVICE_NAMESPACE), service))
return true;
return matchAll(VISIBLE_OSGI_SERVICE_NAMESPACE, service);
}
public boolean isAllowed(BundleCapability capability) {
return isAllowed(capability.getNamespace(), capability.getAttributes());
}
/**
* {@inheritDoc}
*/
@Override
public boolean isAllowed(String namespace, Map<String, ?> attributes) {
if (match(filters.get(namespace), attributes))
return true;
return matchAll(namespace, attributes);
}
@SuppressWarnings("deprecation")
static final String[] serviceNamespaces = new String[] {VISIBLE_OSGI_SERVICE_NAMESPACE, VISIBLE_SERVICE_NAMESPACE};
private boolean matchAll(final String namespace, final Map<String, ?> attributes) {
Collection<Filter> allMatching = filters.get(VISIBLE_ALL_NAMESPACE);
if (allMatching == null) {
return false;
}
return match(allMatching, new AbstractMap<String, Object>() {
@SuppressWarnings("deprecation")
@Override
public Object get(Object key) {
if (RegionFilter.VISIBLE_ALL_NAMESPACE_ATTRIBUTE.equals(key)) {
if (VISIBLE_SERVICE_NAMESPACE.equals(namespace) || VISIBLE_OSGI_SERVICE_NAMESPACE.equals(namespace)) {
return serviceNamespaces;
}
return namespace;
}
return attributes.get(key);
}
@Override
public Set<java.util.Map.Entry<String, Object>> entrySet() {
throw new UnsupportedOperationException();
}
});
}
private boolean matchAll(final String namespace, final ServiceReference<?> service) {
Collection<Filter> allMatching = filters.get(VISIBLE_ALL_NAMESPACE);
if (allMatching == null) {
return false;
}
return match(allMatching, new AbstractMap<String, Object>() {
@SuppressWarnings("deprecation")
@Override
public Object get(Object key) {
if (RegionFilter.VISIBLE_ALL_NAMESPACE_ATTRIBUTE.equals(key)) {
if (VISIBLE_SERVICE_NAMESPACE.equals(namespace) || VISIBLE_OSGI_SERVICE_NAMESPACE.equals(namespace)) {
return serviceNamespaces;
}
return namespace;
}
return service.getProperty((String) key);
}
@Override
public Set<java.util.Map.Entry<String, Object>> entrySet() {
throw new UnsupportedOperationException();
}
});
}
public Map<String, Collection<String>> getSharingPolicy() {
Map<String, Collection<String>> result = new HashMap<String, Collection<String>>((int) ((filters.size() / 0.75) + 1));
for (Map.Entry<String, Collection<Filter>> namespace : filters.entrySet()) {
result.put(namespace.getKey(), getFilters(namespace.getValue()));
}
return result;
}
private static Collection<String> getFilters(Collection<Filter> filters) {
Collection<String> result = new ArrayList<String>(filters.size());
for (Filter filter : filters) {
result.add(filter.toString());
}
return result;
}
public String toString() {
return getSharingPolicy().toString();
}
private Long getBundleId(BundleRevision bundleRevision) {
return EquinoxStateHelper.getBundleId(bundleRevision);
}
}