blob: 6d719a5613283bb7d1eee69a0dc4e7259cb8757e [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.osgi.internal.composite;
import java.net.ContentHandler;
import org.eclipse.osgi.framework.adaptor.BundleData;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.internal.loader.BundleLoaderProxy;
import org.eclipse.osgi.internal.serviceregistry.ServiceReferenceImpl;
import org.eclipse.osgi.service.resolver.BaseDescription;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.osgi.framework.*;
import org.osgi.framework.Constants;
import org.osgi.framework.hooks.service.*;
import org.osgi.service.url.URLStreamHandlerService;
public class CompositePolicy implements ScopePolicy {
private final static BundleDescription[] EMPTY_DESCRIPTIONS = new BundleDescription[0];
private final Framework framework;
private final CompositeInfo rootCompositeInfo = new CompositeInfo(0, Constants.SYSTEM_BUNDLE_SYMBOLICNAME, null, null, null, null, null, null, null, null);
private final static String[] scopedSystemServices = new String[] {URLStreamHandlerService.class.getName().intern(), ContentHandler.class.getName().intern(), EventHook.class.getName().intern(), FindHook.class.getName().intern(), ListenerHook.class.getName().intern()};
public CompositePolicy(Framework framework) {
this.framework = framework;
}
public boolean isVisible(Bundle client, ServiceReference<?> serviceProvider, String[] clazzes) {
return noScopes() || isVisible0((AbstractBundle) client, serviceProvider, clazzes, null);
}
public boolean isVisible(BundleDescription client, BaseDescription constraintProvider) {
return noScopes() || isVisible0(framework.getBundle(client.getBundleId()), null, null, constraintProvider);
}
public boolean isVisible(Bundle client, BaseDescription constraintProvider) {
return noScopes() || isVisible0((AbstractBundle) client, null, null, constraintProvider);
}
public boolean isVisible(BundleData client, BundleData provider) {
return noScopes() || isVisible0(client.getBundleID(), client.getCompositeID(), provider.getBundleID(), provider.getCompositeID(), null, null, createBundleDescription(provider));
}
private BundleDescription createBundleDescription(BundleData provider) {
return CompositeImpl.stateFactory.createBundleDescription(provider.getBundleID(), provider.getSymbolicName(), provider.getVersion(), provider.getLocation(), null, null, null, null, false, true, true, null, null, null, null);
}
public boolean noScopes() {
return rootCompositeInfo.noChildren();
}
private boolean isVisible0(AbstractBundle client, ServiceReference<?> serviceProvider, String[] clazzes, BaseDescription constraintProvider) {
if (client == null)
throw new IllegalArgumentException("Client cannot be null"); //$NON-NLS-1$
if (serviceProvider == null && constraintProvider == null)
throw new IllegalArgumentException("Provider cannot be null"); //$NON-NLS-1$
AbstractBundle providerBundle = null;
if (serviceProvider != null)
// Need to access internals incase the reference has been unregistered (in this case getBundle returns null)
providerBundle = (AbstractBundle) ((ServiceReferenceImpl<?>) serviceProvider).getRegistration().getRegisteringBundle();
else
providerBundle = framework.getBundle(constraintProvider.getSupplier().getBundleId());
if (providerBundle == null)
return false; // we assume the bundle is uninstalled and should not be visible
return isVisible0(client.getBundleId(), client.getCompositeId(), providerBundle.getBundleId(), providerBundle.getCompositeId(), serviceProvider, clazzes, constraintProvider);
}
private boolean isVisible0(long clientID, long clientCompositeID, long providerID, long providerCompositeID, ServiceReference<?> serviceProvider, String[] clazzes, BaseDescription constraintProvider) {
if (serviceProvider == null && constraintProvider == null)
throw new IllegalArgumentException("Provider cannot be null"); //$NON-NLS-1$
if (serviceProvider != null && clientID == 0 && clientCompositeID == 0 && !scopedSystemService(clazzes))
// root system bundle sees every service
return true;
if (providerID == 0 && providerCompositeID == 0 && !scopedSystemService(clazzes))
// Everyone sees the root system bundle' services and packages
return true;
if (clientCompositeID == providerCompositeID)
return true; // in the same composite
CompositeInfo clientInfo = getCompositeInfo(clientCompositeID);
CompositeInfo providerInfo = getCompositeInfo(providerCompositeID);
if (providerInfo == null || clientInfo == providerInfo)
return true;
return clientInfo.isVisible(serviceProvider != null ? (Object) serviceProvider : (Object) constraintProvider, clientInfo, providerInfo);
}
private boolean scopedSystemService(String[] clazzes) {
if (clazzes == null)
return false;
for (int i = 0; i < clazzes.length; i++)
for (int j = 0; j < scopedSystemServices.length; j++)
// we assume the strings are interned
if (clazzes[i] == scopedSystemServices[j])
return true;
return false;
}
public CompositeInfo getCompositeInfo(long compositeId) {
return (compositeId == 0) ? getRootCompositeInfo() : rootCompositeInfo.getChildCompositeInfo(compositeId);
}
public boolean hasBundlePolicyEquivalent(BundleDescription singleton) {
AbstractBundle bundle = framework.getBundle(singleton.getBundleId());
if (bundle == null)
return false; // must be uninstalled
CompositeInfo compositeInfo = getCompositeInfo(bundle.getCompositeId());
if (compositeInfo == null)
return false;
return compositeInfo.hasBundlePolicyEquivalent(singleton);
}
public boolean sameScope(Bundle b1, Bundle b2) {
if (noScopes())
return true;
if (b1 == null || b2 == null)
return false;
long b1CompId = ((AbstractBundle) b1).getCompositeId();
long b2CompId = ((AbstractBundle) b2).getCompositeId();
if (b1CompId == b2CompId)
return true;
if ((b1CompId == 0 && b1.getBundleId() == 0) || (b2CompId == 0 && b2.getBundleId() == 0))
return true; // the root system bundle belongs to every scope
return false;
}
public boolean sameScope(BaseDescription d1, BaseDescription d2) {
if (noScopes())
return true;
if (d1 == null || d2 == null)
return false;
Bundle b1 = framework.getBundle(d1.getSupplier().getBundleId());
Bundle b2 = framework.getBundle(d2.getSupplier().getBundleId());
return sameScope(b1, b2);
}
public BundleDescription[] getScopeContent(BundleDescription desc) {
if (noScopes())
return EMPTY_DESCRIPTIONS;
Object user = desc.getUserObject();
if (!(user instanceof BundleLoaderProxy))
return EMPTY_DESCRIPTIONS;
AbstractBundle bundle = ((BundleLoaderProxy) user).getBundleHost();
if (!(bundle instanceof CompositeImpl))
return EMPTY_DESCRIPTIONS;
// found a composite
return ((CompositeImpl) bundle).getConstituentDescriptions();
}
CompositeInfo getRootCompositeInfo() {
return rootCompositeInfo;
}
}