diff options
52 files changed, 2349 insertions, 937 deletions
diff --git a/bundles/org.eclipse.osgi/.settings/.api_filters b/bundles/org.eclipse.osgi/.settings/.api_filters index a5b74e196..29273de31 100644 --- a/bundles/org.eclipse.osgi/.settings/.api_filters +++ b/bundles/org.eclipse.osgi/.settings/.api_filters @@ -419,6 +419,13 @@ </message_arguments> </filter> </resource> +<resource path="osgi/src/org/osgi/framework/AdaptPermission.java" type="org.osgi.framework.AdaptPermission"> +<filter comment="Ignore OSGi API" id="1110441988"> +<message_arguments> +<message_argument value="org.osgi.framework.AdaptPermission"/> +</message_arguments> +</filter> +</resource> <resource path="osgi/src/org/osgi/framework/AdminPermission.java" type="org.osgi.framework.AdminPermission"> <filter comment="Ignore OSGi API" id="1141899266"> <message_arguments> @@ -920,6 +927,13 @@ </message_arguments> </filter> </resource> +<resource path="osgi/src/org/osgi/framework/hooks/service/ListenerHook.java" type="org.osgi.framework.hooks.service.ListenerHook$ListenerInfo"> +<filter comment="Ignore OSGi APIs" id="403853384"> +<message_arguments> +<message_argument value="org.osgi.framework.hooks.service.ListenerHook.ListenerInfo"/> +</message_arguments> +</filter> +</resource> <resource path="osgi/src/org/osgi/framework/hooks/weaving/WeavingException.java" type="org.osgi.framework.hooks.weaving.WeavingException"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> @@ -969,45 +983,52 @@ </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/BundleRevision.java" type="org.osgi.framework.wiring.BundleRevision"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleCapability.java" type="org.osgi.framework.wiring.BundleCapability"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.BundleRevision"/> +<message_argument value="org.osgi.framework.wiring.BundleCapability"/> </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/BundleWiring.java" type="org.osgi.framework.wiring.BundleWiring"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleRequirement.java" type="org.osgi.framework.wiring.BundleRequirement"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.BundleWiring"/> +<message_argument value="org.osgi.framework.wiring.BundleRequirement"/> </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/BundleWirings.java" type="org.osgi.framework.wiring.BundleWirings"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleRevision.java" type="org.osgi.framework.wiring.BundleRevision"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.BundleWirings"/> +<message_argument value="org.osgi.framework.wiring.BundleRevision"/> </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/Capability.java" type="org.osgi.framework.wiring.Capability"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleRevisions.java" type="org.osgi.framework.wiring.BundleRevisions"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.Capability"/> +<message_argument value="org.osgi.framework.wiring.BundleRevisions"/> </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/FrameworkWiring.java" type="org.osgi.framework.wiring.FrameworkWiring"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleWire.java" type="org.osgi.framework.wiring.BundleWire"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.FrameworkWiring"/> +<message_argument value="org.osgi.framework.wiring.BundleWire"/> </message_arguments> </filter> </resource> -<resource path="osgi/src/org/osgi/framework/wiring/WiredCapability.java" type="org.osgi.framework.wiring.WiredCapability"> +<resource path="osgi/src/org/osgi/framework/wiring/BundleWiring.java" type="org.osgi.framework.wiring.BundleWiring"> <filter comment="Ignore OSGi API" id="1110441988"> <message_arguments> -<message_argument value="org.osgi.framework.wiring.WiredCapability"/> +<message_argument value="org.osgi.framework.wiring.BundleWiring"/> +</message_arguments> +</filter> +</resource> +<resource path="osgi/src/org/osgi/framework/wiring/FrameworkWiring.java" type="org.osgi.framework.wiring.FrameworkWiring"> +<filter comment="Ignore OSGi API" id="1110441988"> +<message_arguments> +<message_argument value="org.osgi.framework.wiring.FrameworkWiring"/> </message_arguments> </filter> </resource> diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java index 024eb8995..9d3b02b38 100644 --- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java +++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BaseDescription.java @@ -12,7 +12,7 @@ package org.eclipse.osgi.service.resolver; import java.util.Map; import org.osgi.framework.Version; -import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.BundleCapability; /** * This class represents a base description object for a state. All description @@ -70,5 +70,5 @@ public interface BaseDescription { * @return the capability represented by this base description * @since 3.7 */ - public Capability getCapability(); + public BundleCapability getCapability(); } diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java index 89d525c19..38f02beb7 100644 --- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java +++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/BundleDescription.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -12,7 +12,6 @@ package org.eclipse.osgi.service.resolver; import java.util.Map; import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.BundleWiring; /** * This class represents a specific version of a bundle in the system. @@ -289,14 +288,4 @@ public interface BundleDescription extends BaseDescription, BundleRevision { * @since 3.4 */ public ExportPackageDescription[] getSubstitutedExports(); - - /** - * Returns the bundle wiring object associated with this bundle description. - * A bundle description can only have one bundle wiring object associated with - * it which is in use. A bundle description must be resolved in order - * to have a bundle wiring object associated with it. - * @return the bundle wiring object associated with this bundle description. - * @since 3.7 - */ - public BundleWiring getBundleWiring(); } diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java index 1996cf1ed..63b9f70ac 100644 --- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java +++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/State.java @@ -10,8 +10,7 @@ *******************************************************************************/ package org.eclipse.osgi.service.resolver; -import java.util.Collection; -import java.util.Dictionary; +import java.util.*; import org.osgi.framework.BundleException; import org.osgi.framework.Version; import org.osgi.framework.hooks.resolver.ResolverHookFactory; @@ -229,11 +228,12 @@ public interface State { * @param selectedCapabilities the selected capabilities for this resolved bundle, can be <code>null</code> * @param resolvedRequires the {@link BundleDescription}s that resolve the required bundles for this bundle, can be <code>null</code> * @param resolvedImports the exported packages that resolve the imports for this bundle, can be <code>null</code> - * @param resolveCapabilities the capabilities that resolve the required capabilities for this bundle, can be <code>null</code> + * @param resolvedCapabilities the capabilities that resolve the required capabilities for this bundle, can be <code>null</code> + * @param resolvedWires the map of state wires for the resolved requirements of the given bundle. The key is the name space of the requirement. * @throws IllegalStateException if this is not done during a call to <code>resolve</code> * @since 3.7 */ - public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolveCapabilities); + public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolvedCapabilities, Map<String, List<StateWire>> resolvedWires); /** * Sets the given removal pending bundle to removal complete for this state. diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java new file mode 100644 index 000000000..2b2afdf4b --- /dev/null +++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/StateWire.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2011 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.service.resolver; + +/** + * A state wire represents a decision made by a resolver to wire a requirement to a capability. + * There are 4 parts to a state wire. + * <ul> + * <li>The requirement which may have been specified by a host bundle or one of its attached fragments.</li> + * <li>The host bundle which is associated with the requirement. There are cases where the host + * bundle may not be the same as the bundle which declared the requirement. For example, if a fragment + * specifies additional requirements.</li> + * <li>The capability which may have been specified by a host bundle or one of its attached fragments.</li> + * <li>The host bundle which is associated with the capability. There are cases where the host + * bundle may not be the same as the bundle which declared the capability. For example, if a fragment + * specifies additional capabilities.</li> + * </ul> + * @since 3.7 + */ +public class StateWire { + private final BundleDescription requirementHost; + private final VersionConstraint declaredRequirement; + private final BundleDescription capabilityHost; + private final BaseDescription declaredCapability; + + /** + * Constructs a new state wire. + * @param requirementHost the bundle hosting the requirement. + * @param declaredRequirement the declared requirement. The bundle declaring the requirement may be different from the requirement host. + * @param capabilityHost the bundle hosting the capability. + * @param declaredCapability the declared capability. The bundle declaring the capability may be different from the capability host. + */ + public StateWire(BundleDescription requirementHost, VersionConstraint declaredRequirement, BundleDescription capabilityHost, BaseDescription declaredCapability) { + super(); + this.requirementHost = requirementHost; + this.declaredRequirement = declaredRequirement; + this.capabilityHost = capabilityHost; + this.declaredCapability = declaredCapability; + + } + + /** + * Gets the requirement host. + * @return the requirement host. + */ + public BundleDescription getRequirementHost() { + return requirementHost; + } + + /** + * Gets the declared requirement. + * @return the declared requirement. + */ + public VersionConstraint getDeclaredRequirement() { + return declaredRequirement; + } + + /** + * gets the capability host. + * @return the capability host. + */ + public BundleDescription getCapabilityHost() { + return capabilityHost; + } + + /** + * gets the declared capability. + * @return the declared capability. + */ + public BaseDescription getDeclaredCapability() { + return declaredCapability; + } +} diff --git a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java index b61ad42b1..10119e154 100644 --- a/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java +++ b/bundles/org.eclipse.osgi/core/adaptor/org/eclipse/osgi/service/resolver/VersionConstraint.java @@ -10,6 +10,8 @@ *******************************************************************************/ package org.eclipse.osgi.service.resolver; +import org.osgi.framework.wiring.BundleRequirement; + /** * VersionConstraints represent the relationship between two bundles (in the * case of bundle requires) or a bundle and a package (in the case of import/export). @@ -70,4 +72,14 @@ public interface VersionConstraint extends Cloneable { * @see #isResolved() */ public BaseDescription getSupplier(); + + /** + * Returns the requirement represented by this constraint. + * Some constraint types may not be able to represent + * a requirement. In such cases <code>null</code> is + * returned. + * @return the requirement represented by this constraint + * @since 3.7 + */ + public BundleRequirement getRequirement(); } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java index d2a784926..36d52ab9a 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/AbstractBundle.java @@ -30,15 +30,14 @@ import org.eclipse.osgi.signedcontent.*; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; import org.osgi.framework.startlevel.BundleStartLevel; -import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.BundleWiring; +import org.osgi.framework.wiring.*; /** * This object is given out to bundles and wraps the internal Bundle object. It * is destroyed when a bundle is uninstalled and reused if a bundle is updated. * This class is abstract and is extended by BundleHost and BundleFragment. */ -public abstract class AbstractBundle implements Bundle, Comparable<Bundle>, KeyedElement, BundleStartLevel, BundleReference { +public abstract class AbstractBundle implements Bundle, Comparable<Bundle>, KeyedElement, BundleStartLevel, BundleReference, BundleRevisions { private final static long STATE_CHANGE_TIMEOUT; static { long stateChangeWait = 5000; @@ -1453,8 +1452,27 @@ public abstract class AbstractBundle implements Bundle, Comparable<Bundle>, Keye } } + public final <A> A adapt(Class<A> adapterType) { + checkAdaptPermission(adapterType); + return adapt0(adapterType); + } + + public List<BundleRevision> getRevisions() { + List<BundleRevision> revisions = new ArrayList<BundleRevision>(); + BundleDescription current = getBundleDescription(); + if (current != null) + revisions.add(current); + BundleDescription[] removals = framework.adaptor.getState().getRemovalPending(); + for (BundleDescription removed : removals) { + if (removed.getBundleId() == getBundleId() && removed != current) { + revisions.add(removed); + } + } + return revisions; + } + @SuppressWarnings("unchecked") - public <A> A adapt(Class<A> adapterType) { + protected <A> A adapt0(Class<A> adapterType) { if (adapterType.isInstance(this)) return (A) this; if (BundleContext.class.equals(adapterType)) { @@ -1464,22 +1482,32 @@ public abstract class AbstractBundle implements Bundle, Comparable<Bundle>, Keye return null; } } - if (BundleStartLevel.class.equals(adapterType)) - return (A) this; - if (BundleWiring.class.equals(adapterType)) { - if (state == UNINSTALLED || isFragment()) + if (state == UNINSTALLED) return null; BundleDescription description = getBundleDescription(); - return (A) description.getBundleWiring(); + return (A) description.getWiring(); } if (BundleRevision.class.equals(adapterType)) { + if (state == UNINSTALLED) + return null; return (A) getBundleDescription(); } return null; } + /** + * Check for permission to get a service. + */ + private <A> void checkAdaptPermission(Class<A> adapterType) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return; + } + sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT)); + } + public File getDataFile(String filename) { return framework.getDataFile(this, filename); } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java index 26fb16328..98ca8ee24 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleFragment.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -13,16 +13,12 @@ package org.eclipse.osgi.framework.internal.core; import java.io.IOException; import java.net.URL; -import java.util.*; +import java.util.Enumeration; import org.eclipse.osgi.framework.adaptor.BundleData; import org.eclipse.osgi.framework.debug.Debug; import org.eclipse.osgi.internal.loader.BundleLoader; -import org.eclipse.osgi.service.resolver.BundleDescription; -import org.eclipse.osgi.service.resolver.HostSpecification; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.framework.wiring.BundleWirings; public class BundleFragment extends AbstractBundle { @@ -335,44 +331,4 @@ public class BundleFragment extends AbstractBundle { // Fragments cannot have a BundleContext. return null; } - - @SuppressWarnings("unchecked") - public <A> A adapt(Class<A> adapterType) { - if (BundleWirings.class.equals(adapterType)) { - return (A) new BundleWirings() { - public Bundle getBundle() { - return BundleFragment.this; - } - - public List<BundleWiring> getWirings() { - List<BundleWiring> wirings = new ArrayList<BundleWiring>(); - BundleDescription current = getBundleDescription(); - BundleDescription[] removed = framework.adaptor.getState().getRemovalPending(); - - int i = -1; - do { - HostSpecification hostSpec = null; - if (i == -1) { - if (current != null) - hostSpec = current.getHost(); - } else if (removed[i] != current && removed[i].getBundleId() == getBundleId()) { - hostSpec = removed[i].getHost(); - } - BundleDescription[] hostDescs = hostSpec == null ? null : hostSpec.getHosts(); - if (hostDescs != null) { - for (BundleDescription host : hostDescs) { - BundleWiring wiring = host.getBundleWiring(); - if (wiring != null) - wirings.add(wiring); - } - } - i++; - } while (i < removed.length); - return wirings; - } - - }; - } - return super.adapt(adapterType); - } } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java index e5ccd70f9..282949a20 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/BundleHost.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -13,7 +13,7 @@ package org.eclipse.osgi.framework.internal.core; import java.io.IOException; import java.net.URL; -import java.util.*; +import java.util.Enumeration; import org.eclipse.osgi.framework.adaptor.*; import org.eclipse.osgi.framework.debug.Debug; import org.eclipse.osgi.framework.log.FrameworkLogEntry; @@ -23,8 +23,6 @@ import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.service.resolver.ResolverHookException; import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; -import org.osgi.framework.wiring.BundleWiring; -import org.osgi.framework.wiring.BundleWirings; public class BundleHost extends AbstractBundle { public static final int LAZY_TRIGGER = 0x40000000; @@ -682,33 +680,4 @@ public class BundleHost extends AbstractBundle { return (bcl instanceof ClassLoader) ? (ClassLoader) bcl : null; } - @SuppressWarnings("unchecked") - public <A> A adapt(Class<A> adapterType) { - if (BundleWirings.class.equals(adapterType)) { - return (A) new BundleWirings() { - public Bundle getBundle() { - return BundleHost.this; - } - - public List<BundleWiring> getWirings() { - List<BundleWiring> wirings = new ArrayList<BundleWiring>(); - BundleWiring current = adapt(BundleWiring.class); - if (current != null) - wirings.add(current); - BundleDescription[] removals = framework.adaptor.getState().getRemovalPending(); - for (BundleDescription removed : removals) { - if (removed.getBundleId() == getBundleId()) { - BundleWiring removedWiring = removed.getBundleWiring(); - if (removedWiring != null && removedWiring != current) - wirings.add(removedWiring); - } - } - return wirings; - } - - }; - } - return super.adapt(adapterType); - } - } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java index d5dda8e05..90a580112 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/CoreResolverHookFactory.java @@ -18,8 +18,7 @@ import org.eclipse.osgi.util.NLS; import org.osgi.framework.*; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.hooks.resolver.ResolverHookFactory; -import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.*; /** * This class encapsulates the delegation to ResolverHooks that are registered with the service @@ -133,13 +132,13 @@ public class CoreResolverHookFactory implements ResolverHookFactory { } } - public void filterSingletonCollisions(Capability singleton, Collection<Capability> collisionCandidates) { + public void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates) { if (Debug.DEBUG_HOOKS) { Debug.println("ResolverHook.filterSingletonCollisions(" + singleton + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } if (hooks.isEmpty()) return; - collisionCandidates = new ShrinkableCollection<Capability>(collisionCandidates); + collisionCandidates = new ShrinkableCollection<BundleCapability>(collisionCandidates); for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); if (hookRef.reference.getBundle() == null) { @@ -154,20 +153,20 @@ public class CoreResolverHookFactory implements ResolverHookFactory { } } - public void filterMatches(BundleRevision requirer, Collection<Capability> candidates) { + public void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates) { if (Debug.DEBUG_HOOKS) { - Debug.println("ResolverHook.filterMatches(" + requirer + ", " + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + Debug.println("ResolverHook.filterMatches(" + requirement + ", " + candidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } if (hooks.isEmpty()) return; - candidates = new ShrinkableCollection<Capability>(candidates); + candidates = new ShrinkableCollection<BundleCapability>(candidates); for (Iterator<HookReference> iHooks = hooks.iterator(); iHooks.hasNext();) { HookReference hookRef = iHooks.next(); if (hookRef.reference.getBundle() == null) { handleHookException(null, hookRef.hook, "filterMatches", hookRef.reference.getBundle(), hooks, true); //$NON-NLS-1$ } else { try { - hookRef.hook.filterMatches(requirer, candidates); + hookRef.hook.filterMatches(requirement, candidates); } catch (Throwable t) { handleHookException(t, hookRef.hook, "filterMatches", hookRef.reference.getBundle(), hooks, true); //$NON-NLS-1$ } diff --git a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java index ad4da2ac6..f19f7657e 100644 --- a/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java +++ b/bundles/org.eclipse.osgi/core/framework/org/eclipse/osgi/framework/internal/core/InternalSystemBundle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -401,12 +401,12 @@ public class InternalSystemBundle extends BundleHost implements org.osgi.framewo @SuppressWarnings("unchecked") @Override - public <A> A adapt(Class<A> adapterType) { + protected <A> A adapt0(Class<A> adapterType) { if (FrameworkStartLevel.class.equals(adapterType)) return (A) fsl; else if (FrameworkWiring.class.equals(adapterType)) return (A) framework.getPackageAdmin(); - return super.adapt(adapterType); + return super.adapt0(adapterType); } class EquinoxStartLevel implements FrameworkStartLevel { diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java index 5f4b42bbe..78b8f44dc 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WeavingHookConfigurator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010 IBM Corporation and others. + * Copyright (c) 2010, 2011 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 @@ -23,8 +23,7 @@ import org.eclipse.osgi.framework.adaptor.ClassLoaderDelegate; import org.eclipse.osgi.framework.internal.core.Framework; import org.eclipse.osgi.internal.loader.BundleLoader; import org.eclipse.osgi.internal.serviceregistry.ServiceRegistry; -import org.osgi.framework.FrameworkEvent; -import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.*; public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHook, ClassLoadingStatsHook { private BaseAdaptor adaptor; @@ -68,7 +67,9 @@ public class WeavingHookConfigurator implements HookConfigurator, ClassLoadingHo try { return wovenClass.callHooks(); } catch (Throwable t) { - adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, manager.getBaseData().getBundle(), t); + ServiceRegistration<?> errorHook = wovenClass.getErrorHook(); + Bundle errorBundle = errorHook != null ? errorHook.getReference().getBundle() : manager.getBaseData().getBundle(); + adaptor.getEventPublisher().publishFrameworkEvent(FrameworkEvent.ERROR, errorBundle, t); // fail hard with a class loading error ClassFormatError error = new ClassFormatError("Unexpected error from weaving hook."); //$NON-NLS-1$ error.initCause(t); diff --git a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java index 9198e8f29..12f2a4b26 100644 --- a/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java +++ b/bundles/org.eclipse.osgi/defaultAdaptor/src/org/eclipse/osgi/internal/baseadaptor/weaving/WovenClassImpl.java @@ -34,6 +34,7 @@ public final class WovenClassImpl implements WovenClass, HookContext { private byte[] bytes; private byte hookFlags = 0; private Throwable error; + private ServiceRegistration<?> errorHook; private Class<?> clazz; public WovenClassImpl(String className, byte[] bytes, ProtectionDomain domain, BundleLoader loader, ServiceRegistry registry, Map<ServiceRegistration<?>, Boolean> blacklist) { @@ -114,7 +115,7 @@ public final class WovenClassImpl implements WovenClass, HookContext { } public BundleWiring getBundleWiring() { - return loader.getLoaderProxy().getBundleDescription().getBundleWiring(); + return loader.getLoaderProxy().getBundleDescription().getWiring(); } public void call(final Object hook, ServiceRegistration<?> hookRegistration) throws Exception { @@ -128,9 +129,11 @@ public final class WovenClassImpl implements WovenClass, HookContext { ((WeavingHook) hook).weave(this); } catch (WeavingException e) { error = e; + errorHook = hookRegistration; // do not blacklist on weaving exceptions } catch (Throwable t) { error = t; // save the error to fail later + errorHook = hookRegistration; // put the registration on the black list blackList.put(hookRegistration, Boolean.TRUE); } @@ -188,4 +191,8 @@ public final class WovenClassImpl implements WovenClass, HookContext { public String toString() { return className; } + + public ServiceRegistration<?> getErrorHook() { + return errorHook; + } } diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/AdaptPermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/AdaptPermission.java new file mode 100644 index 000000000..f95c1fe11 --- /dev/null +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/AdaptPermission.java @@ -0,0 +1,635 @@ +/* + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.osgi.framework; + +import java.io.IOException; +import java.io.NotSerializableException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.security.AccessController; +import java.security.BasicPermission; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * A bundle's authority to adapt an object to a type. + * + * <p> + * {@code AdaptPermission} has one action: {@code adapt}. + * + * @ThreadSafe + * @version $Id: bc4c5d392d2534a7744f6fc00f4665502f82033c $ + */ +public class AdaptPermission extends BasicPermission { + + private static final long serialVersionUID = 1L; + + /** + * The action string {@code initiate}. + */ + public final static String ADAPT = "adapt"; + + private final static int ACTION_ADAPT = 0x00000001; + private final static int ACTION_ALL = ACTION_ADAPT; + final static int ACTION_NONE = 0; + + /** + * The actions mask. + */ + transient int action_mask; + + /** + * The actions in canonical form. + * + * @serial + */ + private volatile String actions = null; + + /** + * The bundle used by this AdaptPermission. + */ + transient final Bundle bundle; + + /** + * This holds a Filter matching object used to evaluate the filter in + * implies. + */ + transient Filter filter; + + /** + * This map holds the properties of the permission, used to match a filter + * in implies. This is not initialized until necessary, and then cached in + * this object. + */ + private transient volatile Map<String, Object> properties; + + /** + * Creates a new granted {@code AdaptPermission} object. + * + * This constructor must only be used to create a permission that is going + * to be checked. + * <p> + * Examples: + * + * <pre> + * (adaptClass=com.acme.*) + * (&(signer=\*,o=ACME,c=US)(adaptClass=com.acme.*)) + * (signer=\*,o=ACME,c=US) + * </pre> + * + * <p> + * When a signer key is used within the filter expression the signer value + * must escape the special filter chars ('*', '(', ')'). + * <p> + * The name is specified as a filter expression. The filter gives access to + * the following attributes: + * <ul> + * <li>signer - A Distinguished Name chain used to sign the exporting + * bundle. Wildcards in a DN are not matched according to the filter string + * rules, but according to the rules defined for a DN chain.</li> + * <li>location - The location of the exporting bundle.</li> + * <li>id - The bundle ID of the exporting bundle.</li> + * <li>name - The symbolic name of the exporting bundle.</li> + * <li>adaptClass - The name of the type to which an object can be adapted.</li> + * </ul> + * Filter attribute names are processed in a case sensitive manner. + * + * @param filter A filter expression. Filter attribute names are processed + * in a case sensitive manner. A special value of {@code "*"} can be + * used to match all adaptations. + * @param actions {@code adapt}. + * @throws IllegalArgumentException If the filter has an invalid syntax. + */ + public AdaptPermission(String filter, String actions) { + this(parseFilter(filter), parseActions(actions)); + } + + /** + * Creates a new requested {@code AdaptPermission} object to be used by the + * code that must perform {@code checkPermission}. {@code AdaptPermission} + * objects created with this constructor cannot be added to an + * {@code AdaptPermission} permission collection. + * + * @param adaptClass The name of the type to which an object can be adapted. + * @param adaptableBundle The bundle associated with the object being + * adapted. + * @param actions {@code adapt}. + */ + public AdaptPermission(String adaptClass, Bundle adaptableBundle, + String actions) { + super(adaptClass); + setTransients(null, parseActions(actions)); + this.bundle = adaptableBundle; + if (adaptClass == null) { + throw new NullPointerException("adaptClass must not be null"); + } + if (adaptableBundle == null) { + throw new NullPointerException("adaptableBundle must not be null"); + } + } + + /** + * Package private constructor used by AdaptPermissionCollection. + * + * @param filter name filter + * @param mask action mask + */ + AdaptPermission(Filter filter, int mask) { + super((filter == null) ? "*" : filter.toString()); + setTransients(filter, mask); + this.bundle = null; + } + + /** + * Called by constructors and when deserialized. + * + * @param filter Permission's filter or {@code null} for wildcard. + * @param mask action mask + */ + private void setTransients(Filter filter, int mask) { + this.filter = filter; + if ((mask == ACTION_NONE) || ((mask & ACTION_ALL) != mask)) { + throw new IllegalArgumentException("invalid action string"); + } + this.action_mask = mask; + } + + /** + * Parse action string into action mask. + * + * @param actions Action string. + * @return action mask. + */ + private static int parseActions(String actions) { + boolean seencomma = false; + + int mask = ACTION_NONE; + + if (actions == null) { + return mask; + } + + char[] a = actions.toCharArray(); + + int i = a.length - 1; + if (i < 0) + return mask; + + while (i != -1) { + char c; + + // skip whitespace + while ((i != -1) + && ((c = a[i]) == ' ' || c == '\r' || c == '\n' + || c == '\f' || c == '\t')) + i--; + + // check for the known strings + int matchlen; + + if (i >= 4 && (a[i - 4] == 'a' || a[i - 4] == 'A') + && (a[i - 3] == 'd' || a[i - 3] == 'D') + && (a[i - 2] == 'a' || a[i - 2] == 'A') + && (a[i - 1] == 'p' || a[i - 1] == 'P') + && (a[i] == 't' || a[i] == 'T')) { + matchlen = 5; + mask |= ACTION_ADAPT; + + } + else { + // parse error + throw new IllegalArgumentException("invalid actions: " + + actions); + } + + // make sure we didn't just match the tail of a word + // like "ackbarfadapt". Also, skip to the comma. + seencomma = false; + while (i >= matchlen && !seencomma) { + switch (a[i - matchlen]) { + case ',' : + seencomma = true; + /* FALLTHROUGH */ + case ' ' : + case '\r' : + case '\n' : + case '\f' : + case '\t' : + break; + default : + throw new IllegalArgumentException( + "invalid permission: " + actions); + } + i--; + } + + // point i at the location of the comma minus one (or -1). + i -= matchlen; + } + + if (seencomma) { + throw new IllegalArgumentException("invalid actions: " + actions); + } + + return mask; + } + + /** + * Parse filter string into a Filter object. + * + * @param filterString The filter string to parse. + * @return a Filter for this bundle. + * @throws IllegalArgumentException If the filter syntax is invalid. + */ + private static Filter parseFilter(String filterString) { + filterString = filterString.trim(); + if (filterString.equals("*")) { + return null; + } + try { + return FrameworkUtil.createFilter(filterString); + } + catch (InvalidSyntaxException e) { + IllegalArgumentException iae = new IllegalArgumentException( + "invalid filter"); + iae.initCause(e); + throw iae; + } + } + + /** + * Determines if the specified permission is implied by this object. + * + * <p> + * This method checks that the filter of the target is implied by the adapt + * class name of this object. The list of {@code AdaptPermission} actions + * must either match or allow for the list of the target object to imply the + * target {@code AdaptPermission} action. + * <p> + * + * @param p The requested permission. + * @return {@code true} if the specified permission is implied by this + * object; {@code false} otherwise. + */ + public boolean implies(Permission p) { + if (!(p instanceof AdaptPermission)) { + return false; + } + AdaptPermission requested = (AdaptPermission) p; + if (bundle != null) { + return false; + } + // if requested permission has a filter, then it is an invalid argument + if (requested.filter != null) { + return false; + } + return implies0(requested, ACTION_NONE); + } + + /** + * Internal implies method. Used by the implies and the permission + * collection implies methods. + * + * @param requested The requested AdaptPermission which has already be + * validated as a proper argument. The requested AdaptPermission must + * not have a filter expression. + * @param effective The effective actions with which to start. + * @return {@code true} if the specified permission is implied by this + * object; {@code false} otherwise. + */ + boolean implies0(AdaptPermission requested, int effective) { + /* check actions first - much faster */ + effective |= action_mask; + final int desired = requested.action_mask; + if ((effective & desired) != desired) { + return false; + } + /* Get filter */ + Filter f = filter; + if (f == null) { + // it's "*" + return true; + } + return f.matches(requested.getProperties()); + } + + /** + * Returns the canonical string representation of the + * {@code AdaptPermission} actions. + * + * <p> + * Always returns present {@code AdaptPermission} actions in the following + * order: {@code adapt}. + * + * @return Canonical string representation of the {@code AdaptPermission} + * actions. + */ + public String getActions() { + String result = actions; + if (result == null) { + actions = result = ADAPT; + } + return result; + } + + /** + * Returns a new {@code PermissionCollection} object suitable for storing + * {@code AdaptPermission} objects. + * + * @return A new {@code PermissionCollection} object. + */ + public PermissionCollection newPermissionCollection() { + return new AdaptPermissionCollection(); + } + + /** + * Determines the equality of two {@code AdaptPermission} objects. + * + * This method checks that specified permission has the same name and + * {@code AdaptPermission} actions as this {@code AdaptPermission} object. + * + * @param obj The object to test for equality with this + * {@code AdaptPermission} object. + * @return {@code true} if {@code obj} is a {@code AdaptPermission}, and has + * the same name and actions as this {@code AdaptPermission} object; + * {@code false} otherwise. + */ + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + + if (!(obj instanceof AdaptPermission)) { + return false; + } + + AdaptPermission cp = (AdaptPermission) obj; + + return (action_mask == cp.action_mask) + && getName().equals(cp.getName()) + && ((bundle == cp.bundle) || ((bundle != null) && bundle + .equals(cp.bundle))); + } + + /** + * Returns the hash code value for this object. + * + * @return A hash code value for this object. + */ + public int hashCode() { + int h = 31 * 17 + getName().hashCode(); + h = 31 * h + getActions().hashCode(); + if (bundle != null) { + h = 31 * h + bundle.hashCode(); + } + return h; + } + + /** + * WriteObject is called to save the state of this permission object to a + * stream. The actions are serialized, and the superclass takes care of the + * name. + */ + private synchronized void writeObject(java.io.ObjectOutputStream s) + throws IOException { + if (bundle != null) { + throw new NotSerializableException("cannot serialize"); + } + // Write out the actions. The superclass takes care of the name + // call getActions to make sure actions field is initialized + if (actions == null) + getActions(); + s.defaultWriteObject(); + } + + /** + * readObject is called to restore the state of this permission from a + * stream. + */ + private synchronized void readObject(java.io.ObjectInputStream s) + throws IOException, ClassNotFoundException { + // Read in the action, then initialize the rest + s.defaultReadObject(); + setTransients(parseFilter(getName()), parseActions(actions)); + } + + /** + * Called by {@code <@link AdaptPermission#implies(Permission)>}. This + * method is only called on a requested permission which cannot have a + * filter set. + * + * @return a map of properties for this permission. + */ + private Map<String, Object> getProperties() { + Map<String, Object> result = properties; + if (result != null) { + return result; + } + final Map<String, Object> map = new HashMap<String, Object>(5); + map.put("adaptClass", getName()); + if (bundle != null) { + AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + map.put("id", new Long(bundle.getBundleId())); + map.put("location", bundle.getLocation()); + String name = bundle.getSymbolicName(); + if (name != null) { + map.put("name", name); + } + SignerProperty signer = new SignerProperty(bundle); + if (signer.isBundleSigned()) { + map.put("signer", signer); + } + return null; + } + }); + } + return properties = map; + } +} + +/** + * Stores a set of {@code AdaptPermission} permissions. + * + * @see java.security.Permission + * @see java.security.Permissions + * @see java.security.PermissionCollection + */ + +final class AdaptPermissionCollection extends PermissionCollection { + static final long serialVersionUID = -3350758995234427603L; + /** + * Collection of permissions. + * + * @serial + * @GuardedBy this + */ + private Map<String, AdaptPermission> permissions; + + /** + * Boolean saying if "*" is in the collection. + * + * @serial + * @GuardedBy this + */ + private boolean all_allowed; + + /** + * Create an empty AdaptPermissions object. + */ + public AdaptPermissionCollection() { + permissions = new HashMap<String, AdaptPermission>(); + all_allowed = false; + } + + /** + * Adds a permission to this permission collection. + * + * @param permission The {@code AdaptPermission} object to add. + * @throws IllegalArgumentException If the specified permission is not a + * {@code AdaptPermission} instance or was constructed with a Bundle + * object. + * @throws SecurityException If this {@code AdaptPermissionCollection} + * object has been marked read-only. + */ + public void add(final Permission permission) { + if (!(permission instanceof AdaptPermission)) { + throw new IllegalArgumentException("invalid permission: " + + permission); + } + if (isReadOnly()) { + throw new SecurityException("attempt to add a Permission to a " + + "readonly PermissionCollection"); + } + + final AdaptPermission ap = (AdaptPermission) permission; + if (ap.bundle != null) { + throw new IllegalArgumentException("cannot add to collection: " + + ap); + } + + final String name = ap.getName(); + synchronized (this) { + Map<String, AdaptPermission> pc = permissions; + final AdaptPermission existing = pc.get(name); + if (existing != null) { + final int oldMask = existing.action_mask; + final int newMask = ap.action_mask; + if (oldMask != newMask) { + pc.put(name, new AdaptPermission(existing.filter, oldMask + | newMask)); + + } + } + else { + pc.put(name, ap); + } + + if (!all_allowed) { + if (name.equals("*")) { + all_allowed = true; + } + } + } + } + + /** + * Determines if the specified permissions implies the permissions expressed + * in {@code permission}. + * + * @param permission The Permission object to compare with this + * {@code AdaptPermission} object. + * @return {@code true} if {@code permission} is a proper subset of a + * permission in the set; {@code false} otherwise. + */ + public boolean implies(final Permission permission) { + if (!(permission instanceof AdaptPermission)) { + return false; + } + final AdaptPermission requested = (AdaptPermission) permission; + /* if requested permission has a filter, then it is an invalid argument */ + if (requested.filter != null) { + return false; + } + + int effective = AdaptPermission.ACTION_NONE; + + Collection<AdaptPermission> perms; + synchronized (this) { + Map<String, AdaptPermission> pc = permissions; + /* short circuit if the "*" Permission was added */ + if (all_allowed) { + AdaptPermission ap = pc.get("*"); + if (ap != null) { + effective |= ap.action_mask; + final int desired = requested.action_mask; + if ((effective & desired) == desired) { + return true; + } + } + } + perms = pc.values(); + } + /* iterate one by one over filteredPermissions */ + for (AdaptPermission perm : perms) { + if (perm.implies0(requested, effective)) { + return true; + } + } + return false; + } + + /** + * Returns an enumeration of all {@code AdaptPermission} objects in the + * container. + * + * @return Enumeration of all {@code AdaptPermission} objects. + */ + public synchronized Enumeration<Permission> elements() { + List<Permission> all = new ArrayList<Permission>(permissions.values()); + return Collections.enumeration(all); + } + + /* serialization logic */ + private static final ObjectStreamField[] serialPersistentFields = { + new ObjectStreamField("permissions", HashMap.class), + new ObjectStreamField("all_allowed", Boolean.TYPE) }; + + private synchronized void writeObject(ObjectOutputStream out) + throws IOException { + ObjectOutputStream.PutField pfields = out.putFields(); + pfields.put("permissions", permissions); + pfields.put("all_allowed", all_allowed); + out.writeFields(); + } + + private synchronized void readObject(java.io.ObjectInputStream in) + throws IOException, ClassNotFoundException { + ObjectInputStream.GetField gfields = in.readFields(); + permissions = (HashMap<String, AdaptPermission>) gfields.get( + "permissions", null); + all_allowed = gfields.get("all_allowed", false); + } +} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java index 435660545..8f4002c9d 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Bundle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. + * Copyright (c) OSGi Alliance (2000, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,8 @@ import java.util.Enumeration; import java.util.List; import java.util.Map; +import org.osgi.framework.wiring.FrameworkWiring; + /** * An installed bundle in the Framework. * @@ -74,7 +76,7 @@ import java.util.Map; * * @ThreadSafe * @noimplement - * @version $Id: 2b49f64e7a633cefc70b438ec9e1f966ff4f8130 $ + * @version $Id: 239108e8d54ff493587b9cdfe1688bdefc5a714c $ */ public interface Bundle extends Comparable<Bundle> { /** @@ -257,8 +259,7 @@ public interface Bundle extends Comparable<Bundle> { * If this bundle's state is {@code UNINSTALLED} then an * {@code IllegalStateException} is thrown. * <p> - * If the Framework implements the optional Start Level service and the - * current start level is less than this bundle's start level: + * If the current start level is less than this bundle's start level: * <ul> * <li>If the {@link #START_TRANSIENT} option is set, then a * {@code BundleException} is thrown indicating this bundle cannot be @@ -512,8 +513,9 @@ public interface Bundle extends Comparable<Bundle> { * <p> * If this bundle has exported any packages that are imported by another * bundle, these packages must remain exported until the - * {@code PackageAdmin.refreshPackages} method has been has been called or - * the Framework is relaunched. + * {@link FrameworkWiring#refreshBundles(java.util.Collection, FrameworkListener...) + * FrameworkWiring.refreshBundles} method has been has been called or the + * Framework is relaunched. * * <p> * The following steps are required to update a bundle: @@ -624,8 +626,9 @@ public interface Bundle extends Comparable<Bundle> { * <p> * If this bundle has exported any packages, the Framework must continue to * make these packages available to their importing bundles until the - * {@code PackageAdmin.refreshPackages} method has been called or the - * Framework is relaunched. + * {@link FrameworkWiring#refreshBundles(java.util.Collection, FrameworkListener...) + * FrameworkWiring.refreshBundles} method has been called or the Framework + * is relaunched. * * <p> * The following steps are required to uninstall a bundle: @@ -1075,7 +1078,7 @@ public interface Bundle extends Comparable<Bundle> { * This method is intended to be used to obtain configuration, setup, * localization and other information from this bundle. This method takes * into account that the "contents" of this bundle can be extended - * with fragments. This "bundle space" is not a namespace with + * with fragments. This "bundle space" is not a name space with * unique members; the same entry name can be present multiple times. This * method therefore returns an enumeration of URL objects. These URLs can * come from different JARs but have the same path name. This method can @@ -1117,15 +1120,15 @@ public interface Bundle extends Comparable<Bundle> { * files. * @param recurse If {@code true}, recurse into subdirectories. Otherwise * only return entries from the specified path. - * @return An enumeration of URL objects for each matching entry, or {@code - * null} if no matching entry could not be found or if the caller - * does not have the appropriate {@code - * AdminPermission[this,RESOURCE]}, and the Java Runtime Environment - * supports permissions. The URLs are sorted such that entries from - * this bundle are returned first followed by the entries from - * attached fragments in attachment order. If this bundle is a - * fragment, then only matching entries in this fragment are - * returned. + * @return An enumeration of URL objects for each matching entry, or + * {@code null} if no matching entry could not be found or if the + * caller does not have the appropriate + * {@code AdminPermission[this,RESOURCE]}, and the Java Runtime + * Environment supports permissions. The URLs are sorted such that + * entries from this bundle are returned first followed by the + * entries from attached fragments in attachment order. If this + * bundle is a fragment, then only matching entries in this fragment + * are returned. * @throws IllegalStateException If this bundle has been uninstalled. * @since 1.3 */ @@ -1204,6 +1207,9 @@ public interface Bundle extends Comparable<Bundle> { * @return The object, of the specified type, to which this bundle has been * adapted or {@code null} if this bundle cannot be adapted to the * specified type. + * @throws SecurityException If the caller does not have the appropriate + * {@code AdaptPermission[type,this,ADAPT]}, and the Java Runtime + * Environment supports permissions. * @since 1.6 */ <A> A adapt(Class<A> type); diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java index f1b5d007c..bcac7906c 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/CapabilityPermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2000, 2010). All Rights Reserved. + * Copyright (c) OSGi Alliance (2000, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ import java.util.Set; * </ul> * * @ThreadSafe - * @version $Id: ad31023478478ecb577e11eb753875cfff57de1b $ + * @version $Id: bab1ac06b46613f6cff39b291295d8b3e51d58ce $ * @since 1.6 */ @@ -133,7 +133,7 @@ public final class CapabilityPermission extends BasicPermission { * <li>location - The location of the bundle providing the capability.</li> * <li>id - The bundle ID of the bundle providing the capability.</li> * <li>name - The symbolic name of the bundle providing the capability.</li> - * <li>capability.namespace - The namespace of the required capability.</li> + * <li>capability.namespace - The name space of the required capability.</li> * </ul> * Since the above attribute names may conflict with attribute names of a * capability, you can prefix an attribute name with '@' in the filter @@ -146,9 +146,9 @@ public final class CapabilityPermission extends BasicPermission { * {@code require} permission allows the owner of this permission to require * a capability matching the attributes. The {@code provide} permission * allows the bundle to provide a capability in the specified capability - * namespace. + * name space. * - * @param name The capability namespace or a filter over the attributes. + * @param name The capability name space or a filter over the attributes. * @param actions {@code require},{@code provide} (canonical order) * @throws IllegalArgumentException If the specified name is a filter * expression and either the specified action is not {@code require} @@ -170,7 +170,7 @@ public final class CapabilityPermission extends BasicPermission { * constructor cannot be added to a {@code CapabilityPermission} permission * collection. * - * @param namespace The requested capability namespace. + * @param namespace The requested capability name space. * @param attributes The requested capability attributes. * @param providingBundle The bundle providing the requested capability. * @param actions The action {@code require}. diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java index c7784683a..b71a12dfd 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/Constants.java @@ -28,7 +28,7 @@ import org.osgi.framework.launch.Framework; * * @since 1.1 * @noimplement - * @version $Id: dfc898e60b6825d9b1dada682a6aecc858daa7f4 $ + * @version $Id: 517c954ed7d34d2ee762933466f69fa03db7cd37 $ */ public interface Constants { @@ -1276,7 +1276,7 @@ public interface Constants { * persists across multiple Framework invocations. * * <p> - * By convention, every bundle has its own unique namespace, starting with + * By convention, every bundle has its own unique name space, starting with * the bundle's identifier (see {@link Bundle#getBundleId}) and followed by * a dot (.). A bundle may use this as the prefix of the persistent * identifiers for the services it registers. diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java index 2cc72cfe9..d30969978 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/FrameworkEvent.java @@ -18,6 +18,9 @@ package org.osgi.framework; import java.util.EventObject; +import org.osgi.framework.startlevel.FrameworkStartLevel; +import org.osgi.framework.wiring.FrameworkWiring; + /** * A general event from the Framework. * @@ -32,7 +35,7 @@ import java.util.EventObject; * * @Immutable * @see FrameworkListener - * @version $Id: 897075a0bc075c0bb89e77d113f05ca84406a073 $ + * @version $Id: e05c6ffd542fa432835961882bf6b15b0620ffb6 $ */ public class FrameworkEvent extends EventObject { @@ -61,7 +64,7 @@ public class FrameworkEvent extends EventObject { * has reached the initial start level. The source of this event is the * System Bundle. * - * @see "The Start Level Service" + * @see "The Start Level Specification" */ public final static int STARTED = 0x00000001; @@ -74,20 +77,21 @@ public class FrameworkEvent extends EventObject { public final static int ERROR = 0x00000002; /** - * A PackageAdmin.refreshPackage operation has completed. + * A FrameworkWiring.refreshBundles operation has completed. * * <p> - * This event is fired when the Framework has completed the refresh packages - * operation initiated by a call to the PackageAdmin.refreshPackages method. - * The source of this event is the System Bundle. + * This event is fired when the Framework has completed the refresh bundles + * operation initiated by a call to the FrameworkWiring.refreshBundles + * method. The source of this event is the System Bundle. * * @since 1.2 - * @see "{@code PackageAdmin.refreshPackages}" + * @see FrameworkWiring#refreshBundles(java.util.Collection, + * FrameworkListener...) */ public final static int PACKAGES_REFRESHED = 0x00000004; /** - * A StartLevel.setStartLevel operation has completed. + * A FrameworkStartLevel.setStartLevel operation has completed. * * <p> * This event is fired when the Framework has completed changing the active @@ -95,7 +99,7 @@ public class FrameworkEvent extends EventObject { * The source of this event is the System Bundle. * * @since 1.2 - * @see "The Start Level Service" + * @see FrameworkStartLevel#setStartLevel(int, FrameworkListener...) */ public final static int STARTLEVEL_CHANGED = 0x00000008; diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java index df72801b2..6383b22bb 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/ServiceFactory.java @@ -45,7 +45,7 @@ package org.osgi.framework; * @param <S> Type of Service * @see BundleContext#getService * @ThreadSafe - * @version $Id: 8b6ee170eba398d06389cded7d4f154ba2f89098 $ + * @version $Id: 94cd1a0127aaad9beb484f557342a8fbd0be2322 $ */ public interface ServiceFactory<S> { @@ -59,12 +59,20 @@ public interface ServiceFactory<S> { * factory can then return a specific service object for each bundle. * * <p> - * The Framework must check that the returned service object is valid. It - * must not be {@code null} and it must be an {@code instanceof} all the - * classes named when the service was registered. If this method throws an - * exception or will be recursively called for the specified bundle or if - * the returned service object is not valid, then {@code null} is returned - * to the bundle. + * The Framework must check that the returned service object is valid. If + * the returned service object is {@code null} or is not an + * {@code instanceof} all the classes named when the service was registered, + * a framework event of type {@link FrameworkEvent#ERROR} is fired + * containing a service exception of type + * {@link ServiceException#FACTORY_ERROR} and {@code null} is returned to + * the bundle. If this method throws an exception, a framework event of type + * {@link FrameworkEvent#ERROR} is fired containing a service exception of + * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception + * as the cause and {@code null} is returned to the bundle. If this method + * is recursively called for the specified bundle, a framework event of type + * {@link FrameworkEvent#ERROR} is fired containing a service exception of + * type {@link ServiceException#FACTORY_RECURSION} and {@code null} is + * returned to the bundle. * * <p> * The Framework caches the valid service object and will return the same @@ -88,6 +96,12 @@ public interface ServiceFactory<S> { * The Framework invokes this method when a service has been released by a * bundle. The service object may then be destroyed. * + * <p> + * If this method throws an exception, a framework event of type + * {@link FrameworkEvent#ERROR} is fired containing a service exception of + * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception + * as the cause. + * * @param bundle The bundle releasing the service. * @param registration The {@code ServiceRegistration} object for the * service being released. diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/resolver/ResolverHook.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/resolver/ResolverHook.java index 6e2ecc8ee..bbde7ffb5 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/resolver/ResolverHook.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/resolver/ResolverHook.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2011). All Rights Reserved. + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,95 +19,113 @@ package org.osgi.framework.hooks.resolver; import java.util.Collection; import org.osgi.framework.Bundle; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRequirement; import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.Capability; import org.osgi.framework.wiring.FrameworkWiring; /** - * OSGi Framework Resolver Hook instances are obtained from the OSGi {@link ResolverHookFactory - * Framework Resolver Hook Factory} service. + * OSGi Framework Resolver Hook instances are obtained from the OSGi + * {@link ResolverHookFactory Framework Resolver Hook Factory} service. * * <p> - * A Resolver Hook instance is called by the framework during a resolve - * process. A resolver hook may influence the outcome of a resolve process by removing entries - * from shrinkable collections that are passed to the hook during a resolve process. A shrinkable - * collection is a {@code Collection} that supports all remove operations. Any other attempts to modify - * a shrinkable collection will result in an {@code UnsupportedOperationException} being thrown. + * A Resolver Hook instance is called by the framework during a resolve process. + * A resolver hook may influence the outcome of a resolve process by removing + * entries from shrinkable collections that are passed to the hook during a + * resolve process. A shrinkable collection is a {@code Collection} that + * supports all remove operations. Any other attempts to modify a shrinkable + * collection will result in an {@code UnsupportedOperationException} being + * thrown. * * <p> - * The following steps outline the way a framework uses the resolver hooks during a resolve - * process. + * The following steps outline the way a framework uses the resolver hooks + * during a resolve process. * <ol> - * <li> Collect a snapshot of registered resolver hook factories that will be called during the - * current resolve process. Any hook factories registered after the snapshot is taken must not be called - * during the current resolve process. A resolver hook factory contained in the snapshot may become - * unregistered during the resolve process. The framework should handle this and stop calling - * the resolver hook instance provided by the unregistered hook factory for the remainder of the resolve process.</li> - * <li> For each registered hook factory call the {@link ResolverHookFactory#begin(Collection)} method to inform the - * hooks about a resolve process beginning and to obtain a Resolver Hook instance that will be used for the duration - * of the resolve process.</li> - * <li> Determine the collection of unresolved bundle revisions that may be considered for resolution during - * the current resolution process and place each of the bundle revisions in a shrinkable collection - * <b>{@code R}</b>. For each resolver hook call the {@link #filterResolvable(Collection)} method with the - * shrinkable collection <b>{@code R}</b>.</li> - * <li> The shrinkable collection <b>{@code R}</b> now contains all the unresolved bundle revisions that may end up - * as resolved at the end of the current resolve process. Any other bundle revisions that - * got removed from the shrinkable collection <b>{@code R}</b> must not end up as resolved at the end - * of the current resolve process.</li> - * <li> For each bundle revision {@code B} left in the shrinkable collection <b>{@code R}</b> that represents a - * singleton bundle do the following: - * <p> - * Determine the collection of available capabilities that have a name space of - * {@link Capability#BUNDLE_CAPABILITY osgi.bundle}, are singletons, and have the same - * symbolic name as the singleton bundle revision <b>{@code B}</b> and place each of the matching - * capabilities into a shrinkable collection <b>{@code S}</b>. - - * Remove the {@link Capability#BUNDLE_CAPABILITY osgi.bundle} capability provided by - * bundle revision <b>{@code B}</b> from shrinkable collection <b>{@code S}</b>. A singleton bundle - * cannot collide with itself. - * - * For each resovler hook call the {@link #filterSingletonCollisions(Capability, Collection)} - * with the {@link Capability#BUNDLE_CAPABILITY osgi.bundle} capability provided by bundle revision - * <b>{@code B}</b> and the shrinkable collection <b>{@code S}</b> - * - * The shrinkable collection <b>{@code S}</b> now contains all singleton {@link Capability#BUNDLE_CAPABILITY - * osgi.bundle} capabilities that can influence the ability of bundle revision <b>{@code B}</b> to resolve. - * </p> - * </li> - * <li> During a resolve process a framework is free to attempt to resolve any or all bundles contained in - * shrinkable collection <b>{@code R}</b>. For each bundle revision <b>{@code B}</b> left in the shrinkable collection - * <b>{@code R}</b> which the framework attempts to resolve the following steps must be followed: - * <p> - * For each requirement <b>{@code T}</b> specified by bundle revision <b>{@code B}</b> determine the - * collection of capabilities that satisfy (or match) the requirement and place each matching capability into - * a shrinkable collection <b>{@code C}</b>. A capability is considered to match a particular requirement - * if its attributes satisfy a specified requirement and the requirer bundle has permission to access the - * capability. + * <li>Collect a snapshot of registered resolver hook factories that will be + * called during the current resolve process. Any hook factories registered + * after the snapshot is taken must not be called during the current resolve + * process. A resolver hook factory contained in the snapshot may become + * unregistered during the resolve process. The framework should handle this and + * stop calling the resolver hook instance provided by the unregistered hook + * factory and the current resolve process must fail. If possible, an exception + * must be thrown to the caller of the API which triggered the resolve process. + * In cases where the the caller is not available a framework event of type + * error should be fired.</li> + * <li>For each registered hook factory call the + * {@link ResolverHookFactory#begin(Collection)} method to inform the hooks + * about a resolve process beginning and to obtain a Resolver Hook instance that + * will be used for the duration of the resolve process.</li> + * <li>Determine the collection of unresolved bundle revisions that may be + * considered for resolution during the current resolution process and place + * each of the bundle revisions in a shrinkable collection {@code R}. For each + * resolver hook call the {@link #filterResolvable(Collection)} method with the + * shrinkable collection {@code R}.</li> + * <li>The shrinkable collection {@code R} now contains all the unresolved + * bundle revisions that may end up as resolved at the end of the current + * resolve process. Any other bundle revisions that got removed from the + * shrinkable collection {@code R} must not end up as resolved at the end of the + * current resolve process.</li> + * <li>For each bundle revision {@code B} left in the shrinkable collection + * {@code R} that represents a singleton bundle do the following:<br/> + * Determine the collection of available capabilities that have a name space of + * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are singletons, + * and have the same symbolic name as the singleton bundle revision {@code B} + * and place each of the matching capabilities into a shrinkable collection + * {@code S}. * - * For each resolver hook call the {@link #filterMatches(BundleRevision, Collection)} with the - * bundle revision <b>{@code B}</b> and the shrinkable collection <b>{@code C}</b>. - * - * The shrinkable collection <b>{@code C}</b> now contains all the capabilities that may be used to - * satisfy the requirement <b>{@code T}</b>. Any other capabilities that got removed from the - * shrinkable collection <b>{@code C}</b> must not be used to satisfy requirement <b>{@code T}</b>. - * </p> - * </li> - * <li> For each resolver hook call the {@link #end()} method to inform the hooks about a resolve - * process ending.</li> + * Remove the {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} + * capability provided by bundle revision {@code B} from shrinkable collection + * {@code S}. A singleton bundle cannot collide with itself. + * + * For each resolver hook call the + * {@link #filterSingletonCollisions(BundleCapability, Collection)} with the + * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capability + * provided by bundle revision {@code B} and the shrinkable collection {@code S} + * + * The shrinkable collection {@code S} now contains all singleton + * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} capabilities that + * can influence the ability of bundle revision {@code B} to resolve.</li> + * <li>During a resolve process a framework is free to attempt to resolve any or + * all bundles contained in shrinkable collection {@code R}. For each bundle + * revision {@code B} left in the shrinkable collection {@code R} which the + * framework attempts to resolve the following steps must be followed: + * <p/> + * For each requirement {@code T} specified by bundle revision {@code B} + * determine the collection of capabilities that satisfy (or match) the + * requirement and place each matching capability into a shrinkable collection + * {@code C}. A capability is considered to match a particular requirement if + * its attributes satisfy a specified requirement and the requirer bundle has + * permission to access the capability. + * + * <p/> + * For each resolver hook call the + * {@link #filterMatches(BundleRequirement, Collection)} with the requirement + * {@code T} and the shrinkable collection {@code C}. + * + * <p/> + * The shrinkable collection {@code C} now contains all the capabilities that + * may be used to satisfy the requirement {@code T}. Any other capabilities that + * got removed from the shrinkable collection {@code C} must not be used to + * satisfy requirement {@code T}.</li> + * <li>For each resolver hook call the {@link #end()} method to inform the hooks + * about a resolve process ending.</li> * </ol> - * In all cases, the order in which the resolver hooks are called is the reverse compareTo ordering of - * their Service References. That is, the service with the highest ranking number must be called first. - * In cases where a shrinkable collection becomes empty the framework is required to call the - * remaining registered hooks. + * In all cases, the order in which the resolver hooks are called is the reverse + * compareTo ordering of their Service References. That is, the service with the + * highest ranking number must be called first. In cases where a shrinkable + * collection becomes empty the framework is required to call the remaining + * registered hooks. * <p> - * Resolver hooks are low level. Implementations of the resolver hook must be careful not to create an unresolvable state which - * is very hard for a developer or a provisioner to diagnose. Resolver hooks also must not be allowed to start another synchronous - * resolve process (e.g. by calling {@link Bundle#start()} or {@link FrameworkWiring#resolveBundles(Collection)}). - * The framework must detect this and throw an {@link IllegalStateException}. + * Resolver hooks are low level. Implementations of the resolver hook must be + * careful not to create an unresolvable state which is very hard for a + * developer or a provisioner to diagnose. Resolver hooks also must not be + * allowed to start another synchronous resolve process (e.g. by calling + * {@link Bundle#start()} or {@link FrameworkWiring#resolveBundles(Collection)} + * ). The framework must detect this and throw an {@link IllegalStateException}. * * @see ResolverHookFactory - * @ThreadSafe - * @version $Id: abc1f4bb4fd57b8bb41855b1282fe22cb13a9654 $ + * @NotThreadSafe + * @version $Id: ea23400257d780706250f8825ec886aaebb0e5d8 $ */ public interface ResolverHook { /** @@ -123,48 +141,52 @@ public interface ResolverHook { void filterResolvable(Collection<BundleRevision> candidates); /** - * Filter singleton collisions hook method. This method is called during the resolve process - * for the specified singleton. The specified singleton represents a singleton capability - * and the specified collection represent a collection of singleton capabilities which are - * considered collision candidates. The singleton capability and the collection of collision + * Filter singleton collisions hook method. This method is called during the + * resolve process for the specified singleton. The specified singleton + * represents a singleton capability and the specified collection represent + * a collection of singleton capabilities which are considered collision + * candidates. The singleton capability and the collection of collision * candidates must all use the same name space. * <p> - * Currently only capabilities with the name space of {@link Capability#BUNDLE_CAPABILITY - * osgi.bundle} can be singletons. In that case all the collision candidates - * have the name space of {@link Capability#BUNDLE_CAPABILITY osgi.bundle}, are singletons, - * and have the same symbolic name as the specified singleton capability. + * Currently only capabilities with the name space of + * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle} can be + * singletons. In that case all the collision candidates have the name space + * of {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}, are + * singletons, and have the same symbolic name as the specified singleton + * capability. * <p> - * In the future, capabilities in other name spaces may support the singleton concept. - * Hook implementations should be prepared to receive calls to this method for - * capabilities in name spaces other than {@link Capability#BUNDLE_CAPABILITY - * osgi.bundle}. + * In the future, capabilities in other name spaces may support the + * singleton concept. Hook implementations should be prepared to receive + * calls to this method for capabilities in name spaces other than + * {@link BundleRevision#BUNDLE_NAMESPACE osgi.wiring.bundle}. * <p> - * This method can filter the list of collision candidates by removing potential collisions. - * Removing a collision candidate will allow the specified singleton to resolve regardless of - * the resolution state of the removed collision candidate. + * This method can filter the list of collision candidates by removing + * potential collisions. Removing a collision candidate will allow the + * specified singleton to resolve regardless of the resolution state of the + * removed collision candidate. * * @param singleton the singleton involved in a resolve process * @param collisionCandidates a collection of singleton collision candidates */ - void filterSingletonCollisions(Capability singleton, Collection<Capability> collisionCandidates); + void filterSingletonCollisions(BundleCapability singleton, Collection<BundleCapability> collisionCandidates); /** * Filter matches hook method. This method is called during the resolve process for the - * specified requirer. The collection of candidates match a requirement for the requirer. + * specified requirement. The collection of candidates match the specified requirement. * This method can filter the collection of matching candidates by removing candidates from * the collection. Removing a candidate will prevent the resolve process from choosing the - * removed candidate to satisfy a requirement for the requirer. + * removed candidate to satisfy the requirement. * <p> * All of the candidates will have the same name space and will - * match a requirement of the requirer. + * match the specified requirement. * <p> * If the Java Runtime Environment supports permissions then the collection of * candidates will only contain candidates for which the requirer has permission to * access. - * @param requirer the bundle revision which contains a requirement - * @param candidates a collection of candidates that match a requirement of the requirer + * @param requirement the requirement to filter candidates for + * @param candidates a collection of candidates that match the requirement */ - void filterMatches(BundleRevision requirer, Collection<Capability> candidates); + void filterMatches(BundleRequirement requirement, Collection<BundleCapability> candidates); /** * This method is called once at the end of the resolve process. diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/service/ListenerHook.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/service/ListenerHook.java index 48538686f..bdac7b590 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/service/ListenerHook.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/service/ListenerHook.java @@ -28,7 +28,7 @@ import org.osgi.framework.BundleContext; * addition and removal. * * @ThreadSafe - * @version $Id: c64053251939f402bb35b6a69fc3009888420872 $ + * @version $Id: c1687e95e568589cf3e6d927b7d372c9f88c5d16 $ */ public interface ListenerHook { @@ -67,6 +67,7 @@ public interface ListenerHook { * which added the Service Listener and the filter with which it was added. * * @ThreadSafe + * @noimplement */ public interface ListenerInfo { /** diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WovenClass.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WovenClass.java index 58cf64f2e..34aa6d2f4 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WovenClass.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/hooks/weaving/WovenClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -35,7 +35,7 @@ import org.osgi.framework.wiring.BundleWiring; * * @NotThreadSafe * @noimplement - * @version $Id: f54547066bd0632e85242cac434a6bb8a759dff6 $ + * @version $Id: c689a4c27dc39af1bf5f51338f1a8eaca1dddc1a $ */ public interface WovenClass { @@ -52,6 +52,9 @@ public interface WovenClass { * * @return The bytes to be used to define the * {@link WovenClass#getClassName() named} class. + * @throws SecurityException If the caller does not have + * {@code AdminPermission[bundle,WEAVE]} and the Java runtime + * environment supports permissions. */ public byte[] getBytes(); @@ -75,6 +78,9 @@ public interface WovenClass { * @throws NullPointerException If newBytes is {@code null}. * @throws IllegalStateException If weaving is {@link #isWeavingComplete() * complete}. + * @throws SecurityException If the caller does not have + * {@code AdminPermission[bundle,WEAVE]} and the Java runtime + * environment supports permissions. */ public void setBytes(byte[] newBytes); @@ -90,6 +96,10 @@ public interface WovenClass { * After weaving is {@link #isWeavingComplete() complete}, this object * becomes effectively immutable and the returned list will be unmodifiable. * + * <p> + * If the Java runtime environment supports permissions, the caller must + * have {@code AdminPermission[bundle,WEAVE]} to modify the returned list. + * * @return A list containing zero or more dynamic import package * descriptions to add to the bundle wiring for this woven class. * This list must throw {@code IllegalArgumentException} if a diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java index 2e9083bb1..672db449b 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/launch/Framework.java @@ -35,7 +35,7 @@ import org.osgi.framework.FrameworkEvent; * * @ThreadSafe * @noimplement - * @version $Id: e403b10bdb5ae9b9e42651ce04003923beacc3d9 $ + * @version $Id: 2be857d06f3605a04f701b59f11e127c0f8940dc $ */ public interface Framework extends Bundle { @@ -51,8 +51,7 @@ public interface Framework extends Bundle { * <li>Have event handling enabled.</li> * <li>Have reified Bundle objects for all installed bundles.</li> * <li>Have registered any framework services. For example, - * {@code PackageAdmin}, {@code ConditionalPermissionAdmin}, - * {@code StartLevel}.</li> + * {@code ConditionalPermissionAdmin}.</li> * <li>Be {@link #adapt(Class) adaptable} to the OSGi defined types to which * a system bundle can be adapted.</li> * </ul> @@ -134,12 +133,10 @@ public interface Framework extends Bundle { * <li>All installed bundles must be started in accordance with each * bundle's persistent <i>autostart setting</i>. This means some bundles * will not be started, some will be started with <i>eager activation</i> - * and some will be started with their <i>declared activation</i> policy. If - * this Framework implements the optional <i>Start Level Service - * Specification</i>, then the start level of this Framework is moved to the - * start level specified by the - * {@link Constants#FRAMEWORK_BEGINNING_STARTLEVEL beginning start level} - * framework property, as described in the <i>Start Level Service + * and some will be started with their <i>declared activation</i> policy. + * The start level of this Framework is moved to the start level specified + * by the {@link Constants#FRAMEWORK_BEGINNING_STARTLEVEL beginning start + * level} framework property, as described in the <i>Start Level * Specification</i>. If this framework property is not specified, then the * start level of this Framework is moved to start level one (1). Any * exceptions that occur during bundle starting must be wrapped in a @@ -153,7 +150,7 @@ public interface Framework extends Bundle { * @throws SecurityException If the caller does not have the appropriate * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime * Environment supports permissions. - * @see "Start Level Service Specification" + * @see "Start Level Specification" */ void start() throws BundleException; @@ -182,12 +179,11 @@ public interface Framework extends Bundle { * <ol> * <li>This Framework's state is set to {@link #STOPPING}.</li> * <li>All installed bundles must be stopped without changing each bundle's - * persistent <i>autostart setting</i>. If this Framework implements the - * optional <i>Start Level Service Specification</i>, then the start level - * of this Framework is moved to start level zero (0), as described in the - * <i>Start Level Service Specification</i>. Any exceptions that occur - * during bundle stopping must be wrapped in a {@link BundleException} and - * then published as a framework event of type {@link FrameworkEvent#ERROR}</li> + * persistent <i>autostart setting</i>. The start level of this Framework is + * moved to start level zero (0), as described in the <i>Start Level + * Specification</i>. Any exceptions that occur during bundle stopping must + * be wrapped in a {@link BundleException} and then published as a framework + * event of type {@link FrameworkEvent#ERROR}</li> * <li>Unregister all services registered by this Framework.</li> * <li>Event handling is disabled.</li> * <li>This Framework's state is set to {@link #RESOLVED}.</li> @@ -205,7 +201,7 @@ public interface Framework extends Bundle { * @throws SecurityException If the caller does not have the appropriate * {@code AdminPermission[this,EXECUTE]}, and the Java Runtime * Environment supports permissions. - * @see "Start Level Service Specification" + * @see "Start Level Specification" */ void stop() throws BundleException; diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleCapability.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleCapability.java new file mode 100644 index 000000000..3114bab5c --- /dev/null +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleCapability.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.framework.wiring; + +import java.util.Map; + +/** + * A capability that has been declared from a {@link BundleRevision bundle + * revision}. + * + * @ThreadSafe + * @noimplement + * @version $Id: BundleCapability.java,v 1.1.2.1 2011/02/14 22:18:14 twatson Exp $ + */ +public interface BundleCapability { + /** + * Returns the name space of this capability. + * + * @return The name space of this capability. + */ + String getNamespace(); + + /** + * Returns the directives of this capability. + * + * @return An unmodifiable map of directive names to directive values for + * this capability, or an empty map if this capability has no + * directives. + */ + Map<String, String> getDirectives(); + + /** + * Returns the attributes of this capability. + * + * @return An unmodifiable map of attribute names to attribute values for + * this capability, or an empty map if this capability has no + * attributes. + */ + Map<String, Object> getAttributes(); + + /** + * Returns the bundle revision declaring this capability. + * + * @return The bundle revision declaring this capability. + */ + BundleRevision getRevision(); +} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRequirement.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRequirement.java new file mode 100644 index 000000000..4ec2b12b4 --- /dev/null +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRequirement.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.framework.wiring; + +import java.util.Map; + +/** + * A requirement that has been declared from a {@link BundleRevision bundle + * revision}. + * + * @ThreadSafe + * @noimplement + * @version $Id: BundleRequirement.java,v 1.1.2.1 2011/02/14 22:18:14 twatson Exp $ + */ +public interface BundleRequirement { + /** + * Returns the name space of this requirement. + * + * @return The name space of this requirement. + */ + String getNamespace(); + + /** + * Returns the directives of this requirement. + * + * @return An unmodifiable map of directive names to directive values for + * this requirement, or an empty map if this requirement has no + * directives. + */ + Map<String, String> getDirectives(); + + /** + * Returns the attributes of this requirement. + * + * @return An unmodifiable map of attribute names to attribute values for + * this requirement, or an empty map if this requirement has no + * attributes. + */ + Map<String, Object> getAttributes(); + + /** + * Returns the bundle revision declaring this requirement. + * + * @return The bundle revision declaring this requirement. + */ + BundleRevision getRevision(); + + /** + * Returns whether the specified capability matches this requirement. + * + * @param capability The capability to match to this requirement. + * @return {@code true} if the specified capability has the same + * {@link #getNamespace() name space} as this requirement and the + * filter for this requirement matches the + * {@link BundleCapability#getAttributes() attributes of the + * specified capability}; {@code false} otherwise. + */ + boolean matches(BundleCapability capability); +} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevision.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevision.java index e9f71d91e..4f8ccca94 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevision.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevision.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,27 +14,40 @@ * limitations under the License. */ - package org.osgi.framework.wiring; import java.util.List; import org.osgi.framework.Bundle; import org.osgi.framework.BundleReference; +import org.osgi.framework.Constants; import org.osgi.framework.Version; /** - * Bundle Revision. Since a bundle update can change the entries in a bundle, - * different bundle wirings for the same bundle can be associated with different - * bundle revisions. + * Bundle Revision. When a bundle is installed and each time a bundle is + * updated, a new bundle revision of the bundle is created. Since a bundle + * update can change the entries in a bundle, different bundle wirings for the + * same bundle can be associated with different bundle revisions. + * + * <p> + * For a bundle that has not been uninstalled, the most recent bundle revision + * is defined to be the current bundle revision. A bundle in the UNINSTALLED + * state does not have a current revision. The current bundle revision for a + * bundle can be obtained by calling {@link Bundle#adapt(Class) bundle.adapt} + * (BundleRevision.class). Since a bundle in the UNINSTALLED state does not have + * a current revision, adapting such a bundle returns {@code null}. * * <p> - * The current bundle revision for a bundle can be obtained by calling - * {@link Bundle#adapt(Class) bundle.adapt}(BundleRevision.class). + * The framework defines name spaces for {@link #PACKAGE_NAMESPACE package}, + * {@link #BUNDLE_NAMESPACE bundle} and {@link #HOST_NAMESPACE host} + * capabilities and requirements. These name spaces are defined only to express + * wiring information by the framework. They must not be used in + * {@link Constants#PROVIDE_CAPABILITY Provide-Capability} and + * {@link Constants#REQUIRE_CAPABILITY Require-Capability} manifest headers. * * @ThreadSafe * @noimplement - * @version $Id: 1a15861159e7071a1eb504afbc3f75f8af1aff01 $ + * @version $Id: 5c029f6074388be25b42893e72012b4bbbc96fce $ */ public interface BundleRevision extends BundleReference { /** @@ -58,15 +71,152 @@ public interface BundleRevision extends BundleReference { /** * Returns the capabilities declared by this bundle revision. * - * @param namespace The name space of the declared capabilities to - * return or {@code null} to return the provided capabilities from - * all name spaces. - * @return A list containing a snapshot of the declared {@link Capability}s, - * or an empty list if this bundle revision declares no capabilities - * in the specified name space. The list contains the provided - * capabilities in the order they are specified in the manifest. + * @param namespace The name space of the declared capabilities to return or + * {@code null} to return the declared capabilities from all name + * spaces. + * @return A list containing a snapshot of the declared + * {@link BundleCapability}s, or an empty list if this bundle + * revision declares no capabilities in the specified name space. + * The list contains the declared capabilities in the order they are + * specified in the manifest. + */ + List<BundleCapability> getDeclaredCapabilities(String namespace); + + /** + * Returns the requirements declared by this bundle revision. + * + * @param namespace The name space of the declared requirements to return or + * {@code null} to return the declared requirements from all name + * spaces. + * @return A list containing a snapshot of the declared + * {@link BundleRequirement}s, or an empty list if this bundle + * revision declares no requirements in the specified name space. + * The list contains the declared requirements in the order they are + * specified in the manifest. + */ + List<BundleRequirement> getDeclaredRequirements(String namespace); + + /** + * Name space for package capabilities and requirements. + * + * <p> + * The name of the package is stored in the capability attribute of the same + * name as this name space ({@value #PACKAGE_NAMESPACE}). The other + * directives and attributes of the package, from the + * {@link Constants#EXPORT_PACKAGE Export-Package} manifest header, can be + * found in the cabability's {@link BundleCapability#getDirectives() + * directives} and {@link BundleCapability#getAttributes() attributes}. The + * {@link Constants#VERSION_ATTRIBUTE version} capability attribute must + * contain the {@link Version} of the package if one is specified or + * {@link Version#emptyVersion} if not specified. The + * {@link Constants#BUNDLE_SYMBOLICNAME_ATTRIBUTE bundle-symbolic-name} + * capability attribute must contain the + * {@link BundleRevision#getSymbolicName() symbolic name} of the provider if + * one is specified. The {@link Constants#BUNDLE_VERSION_ATTRIBUTE + * bundle-version} capability attribute must contain the + * {@link BundleRevision#getVersion() version} of the provider if one is + * specified or {@link Version#emptyVersion} if not specified. + * + * <p> + * The package capabilities provided by the system bundle, that is the + * bundle with id zero, must include the package specified by the + * {@link Constants#FRAMEWORK_SYSTEMPACKAGES} and + * {@link Constants#FRAMEWORK_SYSTEMPACKAGES_EXTRA} framework properties as + * well as any other package exported by the framework implementation. + * + * <p> + * A bundle revision {@link BundleRevision#getDeclaredCapabilities(String) + * declares} zero or more package capabilities (this is, exported packages) + * and {@link BundleRevision#getDeclaredRequirements(String) declares} zero + * or more package requirements. + * <p> + * A bundle wiring {@link BundleWiring#getCapabilities(String) provides} + * zero or more resolved package capabilities (that is, exported packages) + * and {@link BundleWiring#getRequiredWires(String) requires} zero or more + * resolved package requirements (that is, imported packages). The number of + * package wires required by a bundle wiring may change as the bundle wiring + * may dynamically import additional packages. */ - List<Capability> getDeclaredCapabilities(String namespace); + String PACKAGE_NAMESPACE = "osgi.wiring.package"; + + /** + * Name space for bundle capabilities and requirements. + * + * <p> + * The bundle symbolic name of the bundle is stored in the capability + * attribute of the same name as this name space ({@value #BUNDLE_NAMESPACE} + * ). The other directives and attributes of the bundle, from the + * {@link Constants#BUNDLE_SYMBOLICNAME Bundle-SymbolicName} manifest + * header, can be found in the cabability's + * {@link BundleCapability#getDirectives() directives} and + * {@link BundleCapability#getAttributes() attributes}. The + * {@link Constants#BUNDLE_VERSION_ATTRIBUTE bundle-version} capability + * attribute must contain the {@link Version} of the bundle from the + * {@link Constants#BUNDLE_VERSION Bundle-Version} manifest header if one is + * specified or {@link Version#emptyVersion} if not specified. + * + * <p> + * A non-fragment revision + * {@link BundleRevision#getDeclaredCapabilities(String) declares} exactly + * one<sup>†</sup> bundle capability (that is, the bundle can be + * required by another bundle). A fragment revision must not declare a + * bundle capability. + * + * <p> + * A bundle wiring for a non-fragment revision + * {@link BundleWiring#getCapabilities(String) provides} exactly + * one<sup>†</sup> bundle capability (that is, the bundle can be + * required by another bundle) and + * {@link BundleWiring#getRequiredWires(String) requires} zero or more + * bundle capabilities (that is, requires other bundles). + * + * <p> + * † A bundle with no bundle symbolic name (that is, a bundle with + * {@link Constants#BUNDLE_MANIFESTVERSION Bundle-ManifestVersion} + * {@literal <} 2) must not provide a bundle capability. + */ + String BUNDLE_NAMESPACE = "osgi.wiring.bundle"; + + /** + * Name space for host capabilities and requirements. + * + * <p> + * The bundle symbolic name of the bundle is stored in the capability + * attribute of the same name as this name space ({@value #HOST_NAMESPACE}). + * The other directives and attributes of the bundle, from the + * {@link Constants#BUNDLE_SYMBOLICNAME Bundle-SymbolicName} manifest + * header, can be found in the cabability's + * {@link BundleCapability#getDirectives() directives} and + * {@link BundleCapability#getAttributes() attributes}. The + * {@link Constants#BUNDLE_VERSION_ATTRIBUTE bundle-version} capability + * attribute must contain the {@link Version} of the bundle from the + * {@link Constants#BUNDLE_VERSION Bundle-Version} manifest header if one is + * specified or {@link Version#emptyVersion} if not specified. + * + * <p> + * A non-fragment revision + * {@link BundleRevision#getDeclaredCapabilities(String) declares} zero or + * one<sup>†</sup> host capability if the bundle + * {@link Constants#FRAGMENT_ATTACHMENT_DIRECTIVE allows fragments to be + * attached}. A fragment revision must + * {@link BundleRevision#getDeclaredRequirements(String) declare} exactly + * one host requirement. + * + * <p> + * A bundle wiring for a non-fragment revision + * {@link BundleWiring#getCapabilities(String) provides} zero or + * one<sup>†</sup> host capability if the bundle + * {@link Constants#FRAGMENT_ATTACHMENT_DIRECTIVE allows fragments to be + * attached}. A bundle wiring for a fragment revision + * {@link BundleWiring#getRequiredWires(String) requires} a host capability + * for each host to which it is attached. + * + * <p> + * † A bundle with no bundle symbolic name (that is, a bundle with + * {@link Constants#BUNDLE_MANIFESTVERSION Bundle-ManifestVersion} + * {@literal <} 2) must not provide a host capability. + */ + String HOST_NAMESPACE = "osgi.wiring.host"; /** * Returns the special types of this bundle revision. The bundle revision @@ -93,4 +243,13 @@ public interface BundleRevision extends BundleReference { * @see #getTypes() */ int TYPE_FRAGMENT = 0x00000001; + + /** + * Returns the bundle wiring which is using this bundle revision. + * + * @return The bundle wiring which is using this bundle revision or + * {@code null} if no bundle wiring is using this bundle revision. + * @see BundleWiring#getRevision() + */ + BundleWiring getWiring(); } diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevisions.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevisions.java new file mode 100644 index 000000000..ba856b3f3 --- /dev/null +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleRevisions.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) OSGi Alliance (2011). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.framework.wiring; + +import java.util.List; + +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleReference; + +/** + * The {@link BundleRevision bundle revisions} of a bundle. When a bundle is + * installed and each time a bundle is updated, a new bundle revision of the + * bundle is created. For a bundle that has not been uninstalled, the most + * recent bundle revision is defined to be the current bundle revision. A bundle + * in the UNINSTALLED state does not have a current revision. An in use bundle + * revision is associated with an {@link BundleWiring#isInUse() in use} + * {@link BundleWiring}. The current bundle revision, if there is one, and all + * in use bundle revisions are returned. + * + * <p> + * The bundle revisions for a bundle can be obtained by calling + * {@link Bundle#adapt(Class) bundle.adapt}({@link BundleRevisions}.class). + * {@link #getRevisions()} on the bundle. + * + * @ThreadSafe + * @noimplement + * @version $Id: BundleRevisions.java,v 1.1.2.2 2011/02/14 22:18:14 twatson Exp $ + */ +public interface BundleRevisions extends BundleReference { + /** + * Return the bundle revisions for the {@link BundleReference#getBundle() + * referenced} bundle. + * + * <p> + * The result is a list containing the current bundle revision, if there is + * one, and all in use bundle revisions. The list may also contain + * intermediate bundle revisions which are not in use. + * + * <p> + * The list is ordered in reverse chronological order such that the first + * item is the most recent bundle revision and last item is the oldest + * bundle revision. + * + * <p> + * Generally the list will have at least one bundle revision for the bundle: + * the current bundle revision. However, for an uninstalled bundle with no + * in use bundle revisions, the list may be empty. + * + * @return A list containing a snapshot of the {@link BundleRevision}s for + * the referenced bundle. + */ + List<BundleRevision> getRevisions(); +} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWire.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWire.java new file mode 100644 index 000000000..ad420fa60 --- /dev/null +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWire.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) OSGi Alliance (2011). All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.osgi.framework.wiring; + +/** + * A wire connecting a {@link BundleCapability} to a {@link BundleRequirement}. + * + * @ThreadSafe + * @noimplement + * @version $Id: BundleWire.java,v 1.1.2.1 2011/02/14 22:18:14 twatson Exp $ + */ +public interface BundleWire { + /** + * Returns the {@link BundleCapability} for this wire. + * + * @return The {@link BundleCapability} for this wire. + */ + BundleCapability getCapability(); + + /** + * Return the {@link BundleRequirement} for this wire. + * + * @return The {@link BundleRequirement} for this wire. + */ + BundleRequirement getRequirement(); + + /** + * Returns the bundle wiring {@link BundleWiring#getProvidedWires(String) + * providing} the {@link #getCapability() capability}. + * + * <p> + * The bundle revision referenced by the returned bundle wiring may differ + * from the bundle revision reference by the {@link #getCapability() + * capability}. + * + * @return The bundle wiring providing the capability. If the bundle wiring + * providing the capability is not {@link BundleWiring#isInUse() in + * use}, {@code null} will be returned. + */ + BundleWiring getProviderWiring(); + + /** + * Returns the bundle wiring who + * {@link BundleWiring#getRequiredWires(String) requires} the + * {@link #getCapability() capability}. + * + * <p> + * The bundle revision referenced by the returned bundle wiring may differ + * from the bundle revision reference by the {@link #getRequirement() + * requirement}. + * + * @return The bundle wiring whose requirement is wired to the capability. + * If the bundle wiring requiring the capability is not + * {@link BundleWiring#isInUse() in use}, {@code null} will be + * returned. + */ + BundleWiring getRequirerWiring(); +} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWiring.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWiring.java index 2c7149564..c8f19a270 100644 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWiring.java +++ b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWiring.java @@ -1,5 +1,5 @@ /* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. + * Copyright (c) OSGi Alliance (2010, 2011). All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,43 +25,36 @@ import org.osgi.framework.BundleReference; /** * A wiring for a bundle. Each time a bundle is resolved, a new bundle wiring - * for the bundle is created. A bundle wiring consists of a bundle and it - * attached fragments and represents the dependencies with other bundle wirings. + * for the bundle is created. A bundle wiring is associated with a bundle + * revision and represents the dependencies with other bundle wirings. * * <p> * The bundle wiring for a bundle is the {@link #isCurrent() current} bundle - * wiring if the bundle is resolved and the bundle wiring is the most recent - * bundle wiring. All bundles with non-current, in use bundle wirings are - * considered removal pending. A bundle wiring is {@link #isInUse() in use} if - * it is the current wiring or if some other in use bundle wiring is dependent - * upon it. For example, wired to a package exported by the bundle wiring or - * requires the bundle wiring. An in use bundle wiring has a class loader. Once - * a bundle wiring is no longer in use, it is considered stale and is discarded - * by the framework. + * wiring if it is the most recent bundle wiring for the current bundle + * revision. A bundle wiring is {@link #isInUse() in use} if it is the current + * bundle wiring or if some other in use bundle wiring is dependent upon it. For + * example, another bundle wiring is wired to a capability provided by the + * bundle wiring. An in use bundle wiring for a non-fragment bundle has a class + * loader. All bundles with non-current, in use bundle wirings are considered + * removal pending. Once a bundle wiring is no longer in use, it is considered + * stale and is discarded by the framework. * * <p> - * A list of all in use bundle wirings for a bundle can be obtained by calling - * {@link Bundle#adapt(Class) bundle.adapt}({@link BundleWirings}.class). - * {@link BundleWirings#getWirings() getWirings()}. For non-fragment bundles, - * the first item in the returned list is the current bundle wiring. - * - * <p> - * The current bundle wiring for a non-fragment bundle can be obtained by - * calling {@link Bundle#adapt(Class) bundle.adapt}(BundleWiring.class). A - * fragment bundle does not itself have bundle wirings. So calling - * {@link Bundle#adapt(Class) bundle.adapt}(BundleWiring.class) on a fragment - * must return {@code null}. + * The current bundle wiring for a bundle can be obtained by calling + * {@link Bundle#adapt(Class) bundle.adapt}(BundleWiring.class). A bundle in the + * INSTALLED or UNINSTALLED state does not have a current wiring, adapting such + * a bundle returns {@code null}. * * @ThreadSafe * @noimplement - * @version $Id: 77da60ad2f9fdeea7bd9465b633b35f8a06c6cdf $ + * @version $Id: 7a7bc5a26838599519fbd1496248136278b9d1e7 $ */ public interface BundleWiring extends BundleReference { /** * Returns {@code true} if this bundle wiring is the current bundle wiring. - * The bundle wiring for a bundle is the current bundle wiring if the bundle - * is resolved and the bundle wiring is the most recent bundle wiring. All - * bundles with non-current, in use bundle wirings are considered + * The bundle wiring for a bundle is the current bundle wiring if it is the + * most recent bundle wiring for the current bundle revision. All bundles + * with non-current, in use bundle wirings are considered * {@link FrameworkWiring#getRemovalPendingBundles() removal pending}. * * @return {@code true} if this bundle wiring is the current bundle wiring; @@ -83,36 +76,99 @@ public interface BundleWiring extends BundleReference { /** * Returns the capabilities provided by this bundle wiring. * - * @param capabilityNamespace The name space of the provided capabilities to - * return or {@code null} to return the provided capabilities from - * all name spaces. - * @return A list containing a snapshot of the {@link WiredCapability}s, or + * <p> + * A capability may not be required by any bundle wiring and thus there may + * be no {@link #getProvidedWires(String) wires} for the capability. + * + * <p> + * A bundle wiring for a non-fragment revision provides a subset of the + * declared capabilities from the bundle revision and all attached fragment + * revisions. Not all declared capabilities may be provided since some may + * be discarded. For example, if a package is declared to be exported and + * import, only one is selected and the other is discarded. + * + * @param namespace The name space of the capabilities to return or + * {@code null} to return the capabilities from all name spaces. + * @return A list containing a snapshot of the {@link BundleCapability}s, or * an empty list if this bundle wiring provides no capabilities in * the specified name space. If this bundle wiring is not - * {@link #isInUse() in use}, {@code null} will be returned. The - * list contains the provided capabilities in the order they are - * specified in the manifest. + * {@link #isInUse() in use}, {@code null} will be returned. For a + * given name space, the list contains the wires in the order the + * capabilities were specified in the manifests of the + * {@link #getRevision() bundle revision} and the attached fragments + * of this bundle wiring. There is no ordering defined between + * capabilities in different name spaces. + */ + List<BundleCapability> getCapabilities(String namespace); + + /** + * Returns the requirements of this bundle wiring. + * + * <p> + * A bundle wiring for a non-fragment revision has a subset of the declared + * requirements from the bundle revision and all attached fragment + * revisions. Not all declared requirements may be present since some may be + * discarded. For example, if a package is declared to be optionally + * imported and is not actually imported, the requirement must be discarded. + * + * @param namespace The name space of the requirements to return or + * {@code null} to return the requirements from all name spaces. + * @return A list containing a snapshot of the {@link BundleRequirement}s, + * or an empty list if this bundle wiring uses no requirements in + * the specified name space. If this bundle wiring is not + * {@link #isInUse() in use}, {@code null} will be returned. For a + * given name space, the list contains the wires in the order the + * requirements were specified in the manifests of the + * {@link #getRevision() bundle revision} and the attached fragments + * of this bundle wiring. There is no ordering defined between + * requirements in different name spaces. */ - List<WiredCapability> getProvidedCapabilities(String capabilityNamespace); + List<BundleRequirement> getRequirements(String namespace); /** - * Returns the required capabilities used by this bundle wiring. + * Returns the {@link BundleWire}s to the provided {@link BundleCapability + * capabilities} of this bundle wiring. + * + * @param namespace The name space of the capabilities for which to return + * wires or {@code null} to return the wires for the capabilities in + * all name spaces. + * @return A list containing a snapshot of the {@link BundleWire}s for the + * {@link BundleCapability capabilities} of this bundle wiring, or + * an empty list if this bundle wiring has no capabilities in the + * specified name space. If this bundle wiring is not + * {@link #isInUse() in use}, {@code null} will be returned. For a + * given name space, the list contains the wires in the order the + * capabilities were specified in the manifests of the + * {@link #getRevision() bundle revision} and the attached fragments + * of this bundle wiring. There is no ordering defined between + * capabilities in different name spaces. + */ + List<BundleWire> getProvidedWires(String namespace); + + /** + * Returns the {@link BundleWire}s to the {@link BundleRequirement + * requirements} in use by this bundle wiring. * * <p> - * The result of this method can change if this bundle wiring requires - * additional capabilities. + * This method may return different results if this bundle wiring adds wires + * to more requirements. For example, dynamically importing a package will + * establish a new wire to the dynamically imported package. * - * @param capabilityNamespace The name space of the required capabilities to - * return or {@code null} to return the required capabilities from + * @param namespace The name space of the requirements for which to return + * wires or {@code null} to return the wires for the requirements in * all name spaces. - * @return A list containing a snapshot of the {@link WiredCapability}s used - * by this bundle wiring, or an empty list if this bundle wiring - * requires no capabilities in the specified name space. If this - * bundle wiring is not {@link #isInUse() in use}, {@code null} will - * be returned. The list contains the required capabilities in the - * order they are specified in the manifest. + * @return A list containing a snapshot of the {@link BundleWire}s for the + * {@link BundleRequirement requirements} of this bundle wiring, or + * an empty list if this bundle wiring has no requirements in the + * specified name space. If this bundle wiring is not + * {@link #isInUse() in use}, {@code null} will be returned. For a + * given name space, the list contains the wires in the order the + * requirements were specified in the manifests of the + * {@link #getRevision() bundle revision} and the attached fragments + * of this bundle wiring. There is no ordering defined between + * requirements in different name spaces. */ - List<WiredCapability> getRequiredCapabilities(String capabilityNamespace); + List<BundleWire> getRequiredWires(String namespace); /** * Returns the bundle revision for the bundle in this bundle wiring. Since a @@ -126,27 +182,9 @@ public interface BundleWiring extends BundleReference { * may refer to an older revision of the bundle. * * @return The bundle revision for this bundle wiring. + * @see BundleRevision#getWiring() */ - BundleRevision getBundleRevision(); - - /** - * Returns the bundle revisions for all attached fragments of this bundle - * wiring. Since a bundle update can change the entries in a fragment, - * different bundle wirings for the same bundle can have different bundle - * revisions. - * - * <p> - * The bundle revisions in the list are ordered in fragment attachment order - * such that the first revision in the list is the first attached fragment - * and the last revision in the list is the last attached fragment. - * - * @return A list containing a snapshot of the {@link BundleRevision}s for - * all attached fragments attached of this bundle wiring, or an - * empty list if this bundle wiring does not have any attached - * fragments. If this bundle wiring is not {@link #isInUse() in use} - * , {@code null} will be returned. - */ - List<BundleRevision> getFragmentRevisions(); + BundleRevision getRevision(); /** * Returns the class loader for this bundle wiring. Since a bundle refresh @@ -154,7 +192,8 @@ public interface BundleWiring extends BundleReference { * the same bundle will have different class loaders. * * @return The class loader for this bundle wiring. If this bundle wiring is - * not {@link #isInUse() in use}, {@code null} will be returned. + * not {@link #isInUse() in use} or this bundle wiring is for a + * fragment revision, {@code null} will be returned. * @throws SecurityException If the caller does not have the appropriate * {@code RuntimePermission("getClassLoader")}, and the Java Runtime * Environment supports permissions. @@ -162,16 +201,16 @@ public interface BundleWiring extends BundleReference { ClassLoader getClassLoader(); /** - * Returns entries in this bundle wiring's {@link #getBundleRevision() - * bundle revision} and its attached {@link #getFragmentRevisions() fragment - * revisions}. This bundle wiring's class loader is not used to search for - * entries. Only the contents of this bundle wiring's bundle revision and - * its attached fragment revisions are searched for the specified entries. + * Returns entries in this bundle wiring's {@link #getRevision() bundle + * revision} and its attached fragment revisions. This bundle wiring's class + * loader is not used to search for entries. Only the contents of this + * bundle wiring's bundle revision and its attached fragment revisions are + * searched for the specified entries. * * <p> * This method takes into account that the "contents" of this * bundle wiring can have attached fragments. This "bundle space" - * is not a namespace with unique members; the same entry name can be + * is not a name space with unique members; the same entry name can be * present multiple times. This method therefore returns a list of URL * objects. These URLs can come from different JARs but have the same path * name. This method can either return only entries in the specified path or @@ -199,15 +238,15 @@ public interface BundleWiring extends BundleReference { * {@link #FINDENTRIES_RECURSE}. The method must ignore unrecognized * options. * @return An unmodifiable list of URL objects for each matching entry, or - * an empty list if no matching entry could not be found or if the - * caller does not have the appropriate - * {@code AdminPermission[bundle,RESOURCE]} and the Java Runtime - * Environment supports permissions. The list is ordered such that - * entries from the {@link #getBundleRevision() bundle revision} are - * returned first followed by the entries from - * {@link #getFragmentRevisions() attached fragment revisions} in - * attachment order. If this bundle wiring is not {@link #isInUse() - * in use}, {@code null} must be returned. + * an empty list if no matching entry could not be found, if this + * bundle wiring is for a fragment revision or if the caller does + * not have the appropriate {@code AdminPermission[bundle,RESOURCE]} + * and the Java Runtime Environment supports permissions. The list + * is ordered such that entries from the {@link #getRevision() + * bundle revision} are returned first followed by the entries from + * attached fragment revisions in attachment order. If this bundle + * wiring is not {@link #isInUse() in use}, {@code null} must be + * returned. * @see Bundle#findEntries(String, String, boolean) */ List<URL> findEntries(String path, String filePattern, int options); @@ -257,7 +296,8 @@ public interface BundleWiring extends BundleReference { * This method must ignore unrecognized options. * @return An unmodifiable collection of resource names for each matching * resource, or an empty collection if no matching resource could - * not be found or if the caller does not have the appropriate + * not be found, if this bundle wiring is for a fragment revision or + * if the caller does not have the appropriate * {@code AdminPermission[bundle,RESOURCE]} and the Java Runtime * Environment supports permissions. The collection is unordered and * must contain no duplicate resource names. If this bundle wiring @@ -283,11 +323,10 @@ public interface BundleWiring extends BundleReference { /** * The list resource names operation must limit the result to the names of * matching resources contained in this bundle wiring's - * {@link #getBundleRevision() bundle revision} and its attached - * {@link #getFragmentRevisions() fragment revisions}. The result must not - * include resource names for resources in - * {@link Capability#PACKAGE_CAPABILITY package} names which are - * {@link #getRequiredCapabilities(String) imported} by this wiring. + * {@link #getRevision() bundle revision} and its attached fragment + * revisions. The result must not include resource names for resources in + * {@link BundleRevision#PACKAGE_NAMESPACE package} names which are + * {@link #getRequiredWires(String) imported} by this wiring. * * <p> * This bit may be set when calling diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWirings.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWirings.java deleted file mode 100644 index f1e2d5256..000000000 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/BundleWirings.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.osgi.framework.wiring; - -import java.util.List; - -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleReference; - -/** - * The {@link BundleWiring#isInUse() in use} bundle wirings for a bundle. Each - * time a bundle is resolved, a new bundle wiring of the bundle is created. A - * bundle wiring consists of a bundle and its attached fragments and represents - * the dependencies with other bundle wirings. - * - * <p> - * The in use bundle wirings for a bundle can be obtained by calling - * {@link Bundle#adapt(Class) bundle.adapt}({@link BundleWirings}.class). - * {@link BundleWirings#getWirings() getWirings()}. - * - * @ThreadSafe - * @noimplement - * @version $Id: ecf3e7820319a6710f4dff063577bd052f5dafe2 $ - */ -public interface BundleWirings extends BundleReference { - /** - * Return the {@link BundleWiring#isInUse() in use} wirings for the - * {@link BundleReference#getBundle() referenced} bundle. - * - * <p> - * If the referenced bundle is a non-fragment bundle, then the result is a - * list of in use bundle wirings. The list is ordered in reverse - * chronological order such that the first bundle wiring is the - * {@link BundleWiring#isCurrent() current} bundle wiring and last wiring is - * the oldest in use bundle wiring. - * - * <p> - * If the referenced bundle is a fragment bundle, then the result is a list - * of in use bundle wirings to which the referenced fragment bundle is - * attached. The ordering of the list is unspecified. If the fragment bundle - * is not attached to any bundle wiring, then the returned list will be - * empty. - * - * <p> - * The list must only contain in use bundle wirings. Generally the list will - * have at least one bundle wiring for the bundle: the current bundle - * wiring. However, for an uninstalled bundle with no in use bundle wirings - * or a newly installed bundle which has not been resolved, the list will be - * empty. - * - * @return A list containing a snapshot of the {@link BundleWiring}s for the - * referenced bundle. - */ - List<BundleWiring> getWirings(); -} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/Capability.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/Capability.java deleted file mode 100644 index fc9e5b01c..000000000 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/Capability.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.osgi.framework.wiring; - -import java.util.Map; - -import org.osgi.framework.Constants; -import org.osgi.framework.Version; - -/** - * A capability that has been declared from a {@link BundleRevision bundle - * revision}. - * - * <p> - * The framework defines capabilities for {@link #PACKAGE_CAPABILITY packages}, - * {@link #BUNDLE_CAPABILITY bundles} and {@link #HOST_CAPABILITY hosts}. These - * capabilities are defined only to express wiring information by the framework. - * They must not be used in {@link Constants#PROVIDE_CAPABILITY - * Provide-Capability} and {@link Constants#REQUIRE_CAPABILITY - * Require-Capability} manifest headers. - * - * @ThreadSafe - * @noimplement - * @version $Id: 6b7ced3912cc0570547c06bb4140b78d36d7ee42 $ - */ -public interface Capability { - /** - * Capability name space for package capabilities. The name of the package - * is stored in the capability attribute of the same name as this name - * space. The other directives and attributes of the package, from the - * {@link Constants#EXPORT_PACKAGE Export-Package} manifest header, can be - * found in the cabability's {@link #getDirectives() directives} and - * {@link #getAttributes() attributes}. The - * {@link Constants#VERSION_ATTRIBUTE version} capability attribute must - * contain the {@link Version} of the package if one is specified. The - * {@link Constants#BUNDLE_SYMBOLICNAME_ATTRIBUTE bundle-symbolic-name} - * capability attribute must contain the {@link - * BundleRevision#getSymbolicName() symbolic name} of the provider if one - * is specified. - * The {@link Constants#BUNDLE_VERSION_ATTRIBUTE bundle-version} capability - * attribute must contain the {@link BundleRevision#getVersion() version} - * of the provider if one is specified. - * - * <p> - * The package capabilities provided by the system bundle, that is the - * bundle with id zero, must include the package specified by the - * {@link Constants#FRAMEWORK_SYSTEMPACKAGES} and - * {@link Constants#FRAMEWORK_SYSTEMPACKAGES_EXTRA} framework properties as - * well as any other package exported by the framework implementation. - * - * <p> - * A bundle revision {@link BundleRevision#getDeclaredCapabilities(String) - * declares} zero or more package capabilities (this is, exported packages). - * <p> - * A bundle wiring {@link BundleWiring#getProvidedCapabilities(String) - * provides} zero or more resolved package capabilities (that is, exported packages) - * and {@link BundleWiring#getRequiredCapabilities(String) requires} zero or - * more resolved package capabilities (that is, imported packages). The number of - * package capabilities required by a bundle wiring may change as the bundle - * wiring may dynamically import additional packages. - */ - String PACKAGE_CAPABILITY = "osgi.package"; - - /** - * Capability name space for bundle capabilities. The bundle symbolic name - * of the bundle is stored in the capability attribute of the same name as - * this name space. The other directives and attributes of the bundle, from - * the {@link Constants#BUNDLE_SYMBOLICNAME Bundle-SymbolicName} manifest - * header, can be found in the cabability's {@link #getDirectives() - * directives} and {@link #getAttributes() attributes}. The - * {@link Constants#BUNDLE_VERSION_ATTRIBUTE bundle-version} capability - * attribute must contain the {@link Version} of the bundle, from the - * {@link Constants#BUNDLE_VERSION Bundle-Version} manifest header. - * - * <p> - * A bundle wiring {@link BundleWiring#getProvidedCapabilities(String) - * provides} exactly one<sup>†</sup> bundle capability (that is, the - * bundle can be required by another bundle) and - * {@link BundleWiring#getRequiredCapabilities(String) requires} zero or - * more bundle capabilities (that is, requires other bundles). - * - * <p> - * † A bundle with no bundle symbolic name (that is, a bundle with - * {@link Constants#BUNDLE_MANIFESTVERSION Bundle-ManifestVersion} - * {@literal <} 2) must not provide a bundle capability. - */ - String BUNDLE_CAPABILITY = "osgi.bundle"; - - /** - * Capability name space for host capabilities. The bundle symbolic name of - * the bundle is stored in the capability attribute of the same name as this - * name space. The other directives and attributes of the bundle, from the - * {@link Constants#BUNDLE_SYMBOLICNAME Bundle-SymbolicName} manifest - * header, can be found in the cabability's {@link #getDirectives() - * directives} and {@link #getAttributes() attributes}. The - * {@link Constants#BUNDLE_VERSION_ATTRIBUTE bundle-version} capability - * attribute must contain the {@link Version} of the bundle, from the - * {@link Constants#BUNDLE_VERSION Bundle-Version} manifest header. - * - * <p> - * A bundle wiring {@link BundleWiring#getProvidedCapabilities(String) - * provides} zero or one<sup>†</sup> host capability if the bundle - * {@link Constants#FRAGMENT_ATTACHMENT_DIRECTIVE allows fragments to be - * attached} and {@link BundleWiring#getRequiredCapabilities(String) - * requires} zero or one host capability if their are attached fragments. - * - * <p> - * † A bundle with no bundle symbolic name (that is, a bundle with - * {@link Constants#BUNDLE_MANIFESTVERSION Bundle-ManifestVersion} - * {@literal <} 2) must not provide a host capability. - */ - String HOST_CAPABILITY = "osgi.host"; - - /** - * Returns the name space of this capability. - * - * @return The name space of this capability. - */ - String getNamespace(); - - /** - * Returns the directives of this capability. - * - * @return An unmodifiable map of directive names to directive values for this - * capability, or an empty map if this capability has no directives. - */ - Map<String, String> getDirectives(); - - /** - * Returns the attributes of this capability. - * - * @return An unmodifiable map of attribute names to attribute values for this - * capability, or an empty map if this capability has no attributes. - */ - Map<String, Object> getAttributes(); - - /** - * Returns the bundle revision declaring this capability. - * - * @return The bundle revision declaring this capability. - */ - BundleRevision getProviderRevision(); -} diff --git a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/WiredCapability.java b/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/WiredCapability.java deleted file mode 100644 index d2e40ec44..000000000 --- a/bundles/org.eclipse.osgi/osgi/src/org/osgi/framework/wiring/WiredCapability.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) OSGi Alliance (2010). All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.osgi.framework.wiring; - -import java.util.Collection; - -/** - * A wired capability that has been provided from a {@link BundleWiring bundle wiring}. - * This capability may or may not be required by any bundle wiring. - * <p> - * A wired capability represents a capability from a resolved bundle wiring. - * @ThreadSafe - * @noimplement - * @version $Id: bdf793be0ba691b543c523ca1b608e356aac9963 $ - */ -public interface WiredCapability extends Capability { - /** - * Returns the bundle wiring providing this capability. - * - * @return The bundle wiring providing this capability. If the bundle wiring - * providing this capability is not {@link BundleWiring#isInUse() in - * use}, {@code null} will be returned. - */ - BundleWiring getProviderWiring(); - - /** - * Returns the bundle wirings that require this capability. - * - * <p> - * The result of this method can change if this capability becomes required - * by additional bundle wirings. - * - * @return A collection containing a snapshot of the bundle wirings - * currently requiring this capability, or an empty collection if no - * bundle wirings require this capability. If the bundle wiring - * providing this capability is not {@link BundleWiring#isInUse() in - * use}, {@code null} will be returned. - */ - Collection<BundleWiring> getRequirerWirings(); -} diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java index 8aff6b6f4..7eb0e0827 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverBundle.java @@ -12,6 +12,8 @@ package org.eclipse.osgi.internal.module; import java.util.*; import java.util.Map.Entry; +import org.eclipse.osgi.internal.resolver.ExportPackageDescriptionImpl; +import org.eclipse.osgi.internal.resolver.GenericDescriptionImpl; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.Constants; @@ -351,7 +353,6 @@ public class ResolverBundle extends VersionSupplier implements Comparable<Resolv ArrayList<ResolverExport> hostExports = new ArrayList<ResolverExport>(newExports.length); if (newExports.length > 0 && dynamicAttach) { - StateObjectFactory factory = resolver.getState().getFactory(); for (int i = 0; i < newExports.length; i++) { ResolverExport currentExports[] = getExports(newExports[i].getName()); boolean foundEquivalent = false; @@ -360,7 +361,7 @@ public class ResolverBundle extends VersionSupplier implements Comparable<Resolv foundEquivalent = true; } if (!foundEquivalent) { - ExportPackageDescription hostExport = factory.createExportPackageDescription(newExports[i].getName(), newExports[i].getVersion(), newExports[i].getDirectives(), newExports[i].getAttributes(), true, getBundleDescription()); + ExportPackageDescription hostExport = new ExportPackageDescriptionImpl(getBundleDescription(), newExports[i]); hostExports.add(new ResolverExport(this, hostExport)); } } @@ -369,17 +370,8 @@ public class ResolverBundle extends VersionSupplier implements Comparable<Resolv List<GenericCapability> hostCapabilities = new ArrayList<GenericCapability>(newGenericCapabilities.length); if (newGenericCapabilities.length > 0 && dynamicAttach) { - StateObjectFactory factory = resolver.getState().getFactory(); for (GenericDescription capability : newGenericCapabilities) { - Dictionary<String, Object> origAttrs = capability.getAttributes(); - Map<String, Object> attrs = new HashMap<String, Object>(); - if (origAttrs != null) { - for (Enumeration<String> keys = origAttrs.keys(); keys.hasMoreElements();) { - String key = keys.nextElement(); - attrs.put(key, origAttrs.get(key)); - } - } - GenericDescription hostCapabililty = factory.createGenericDescription(capability.getType(), attrs, null, getBundleDescription()); + GenericDescription hostCapabililty = new GenericDescriptionImpl(getBundleDescription(), capability); hostCapabilities.add(new GenericCapability(this, hostCapabililty)); } fragmentGenericCapabilities.put(fragment.bundleID, hostCapabilities); diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java index 5d6f46c3a..759898a70 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverConstraint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2010 IBM Corporation and others. All rights reserved. This + * Copyright (c) 2005, 2011 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 @@ -10,6 +10,7 @@ package org.eclipse.osgi.internal.module; import org.eclipse.osgi.service.resolver.BundleDescription; import org.eclipse.osgi.service.resolver.VersionConstraint; +import org.osgi.framework.wiring.BundleRequirement; /* * A companion to VersionConstraint from the state used while resolving @@ -17,12 +18,14 @@ import org.eclipse.osgi.service.resolver.VersionConstraint; public abstract class ResolverConstraint { final protected ResolverBundle bundle; protected VersionConstraint constraint; + private BundleRequirement requrement; private VersionSupplier[] possibleSuppliers; private int selectedSupplierIndex = 0; ResolverConstraint(ResolverBundle bundle, VersionConstraint constraint) { this.bundle = bundle; this.constraint = constraint; + this.requrement = constraint.getRequirement(); } // returns the Resolver bundle requiring the ResolverConstraint @@ -139,5 +142,10 @@ public abstract class ResolverConstraint { void setVersionConstraint(VersionConstraint constraint) { this.constraint = constraint; + this.requrement = constraint.getRequirement(); + } + + BundleRequirement getRequirement() { + return requrement; } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java index 7652a122e..d8a800f73 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/ResolverImpl.java @@ -27,8 +27,8 @@ import org.eclipse.osgi.util.ManifestElement; import org.osgi.framework.Filter; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.hooks.resolver.ResolverHook; +import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.Capability; public class ResolverImpl implements Resolver { // Debug fields @@ -349,21 +349,21 @@ public class ResolverImpl implements Resolver { BundleConstraint hostConstraint = bundle.getHost(); List<ResolverBundle> hosts = resolverBundles.get(hostConstraint.getVersionConstraint().getName()); List<ResolverBundle> candidates = new ArrayList<ResolverBundle>(hosts); - List<Capability> hostCapabilities = new ArrayList<Capability>(hosts.size()); + List<BundleCapability> hostCapabilities = new ArrayList<BundleCapability>(hosts.size()); // Must remove candidates that do not match before calling hooks. for (Iterator<ResolverBundle> iCandidates = candidates.iterator(); iCandidates.hasNext();) { ResolverBundle host = iCandidates.next(); if (!host.isResolvable() || !host.getBundleDescription().attachFragments() || !hostConstraint.isSatisfiedBy(host)) { iCandidates.remove(); } else { - List<Capability> h = host.getBundleDescription().getDeclaredCapabilities(Capability.HOST_CAPABILITY); + List<BundleCapability> h = host.getBundleDescription().getDeclaredCapabilities(BundleRevision.HOST_NAMESPACE); // the bundle must have 1 host capability. hostCapabilities.add(h.get(0)); } } if (hook != null) - hook.filterMatches(bundle.getBundleDescription(), asCapabilities(new ArrayMap<Capability, ResolverBundle>(hostCapabilities, candidates))); + hook.filterMatches(hostConstraint.getRequirement(), asCapabilities(new ArrayMap<BundleCapability, ResolverBundle>(hostCapabilities, candidates))); // we are left with only candidates that satisfy the host constraint for (ResolverBundle host : candidates) { foundMatch = true; @@ -435,6 +435,10 @@ public class ResolverImpl implements Resolver { usesCalculationTimeout = false; resolveBundles(bundles, platformProperties, hookDisabled); + // reorder exports and bundles after resolving the bundles + resolverExports.reorder(); + resolverBundles.reorder(); + reorderGenerics(); if (resolveOptional) resolveOptionalConstraints(currentlyResolved); if (DEBUG) @@ -515,7 +519,7 @@ public class ResolverImpl implements Resolver { resolvedOptional = true; } if (resolvedOptional) { - state.resolveBundle(bundle.getBundleDescription(), false, null, null, null, null, null, null, null); + state.resolveBundle(bundle.getBundleDescription(), false, null, null, null, null, null, null, null, null); stateResolveConstraints(bundle); stateResolveBundle(bundle); } @@ -575,7 +579,7 @@ public class ResolverImpl implements Resolver { continue; } List<ResolverBundle> collisionCandidates = new ArrayList<ResolverBundle>(sameBSN.size() - 1); - List<Capability> capabilities = new ArrayList<Capability>(sameBSN.size() - 1); + List<BundleCapability> capabilities = new ArrayList<BundleCapability>(sameBSN.size() - 1); for (ResolverBundle collision : sameBSN) { if (collision == singleton || !collision.getBundleDescription().isSingleton() || !collision.isResolvable()) continue; // Ignore the bundle we are checking and non-singletons and non-resovlable @@ -583,7 +587,7 @@ public class ResolverImpl implements Resolver { capabilities.add(collision.getCapability()); } if (hook != null) - hook.filterSingletonCollisions(singleton.getCapability(), asCapabilities(new ArrayMap<Capability, ResolverBundle>(capabilities, collisionCandidates))); + hook.filterSingletonCollisions(singleton.getCapability(), asCapabilities(new ArrayMap<BundleCapability, ResolverBundle>(capabilities, collisionCandidates))); if (collisionCandidates.isEmpty()) { if (!selected.contains(singleton)) selected.add(singleton); @@ -669,7 +673,7 @@ public class ResolverImpl implements Resolver { continue; if (!bundles[i].isResolved()) continue; - if (!helper.giveExports(getExportsWiredTo(bundles[i]))) { + if (!helper.giveExports(getExportsWiredTo(bundles[i], null))) { state.addResolverError(bundles[i].getBundleDescription(), ResolverError.DISABLED_BUNDLE, null, null); bundles[i].setResolvable(false); // We pass false for keepFragmentsAttached because we need to redo the attachments (bug 272561) @@ -1123,8 +1127,8 @@ public class ResolverImpl implements Resolver { } @SuppressWarnings("unchecked") - static Collection<Capability> asCapabilities(Collection<? extends Capability> capabilities) { - return (Collection<Capability>) capabilities; + static Collection<BundleCapability> asCapabilities(Collection<? extends BundleCapability> capabilities) { + return (Collection<BundleCapability>) capabilities; } private void resolveFragment(ResolverBundle fragment) { @@ -1292,7 +1296,7 @@ public class ResolverImpl implements Resolver { else capabilities = name == null || "*".equals(name) ? namespace.getAllValues() : namespace.get(name); //$NON-NLS-1$ List<GenericCapability> candidates = new ArrayList<GenericCapability>(capabilities); - List<Capability> genCapabilities = new ArrayList<Capability>(candidates.size()); + List<BundleCapability> genCapabilities = new ArrayList<BundleCapability>(candidates.size()); // Must remove candidates that do not match before calling hooks. for (Iterator<GenericCapability> iCandidates = candidates.iterator(); iCandidates.hasNext();) { GenericCapability capability = iCandidates.next(); @@ -1303,7 +1307,7 @@ public class ResolverImpl implements Resolver { } } if (hook != null) - hook.filterMatches(constraint.getBundle().getBundleDescription(), asCapabilities(new ArrayMap<Capability, GenericCapability>(genCapabilities, candidates))); + hook.filterMatches(constraint.getRequirement(), asCapabilities(new ArrayMap<BundleCapability, GenericCapability>(genCapabilities, candidates))); boolean result = false; // We are left with only capabilities that satisfy the constraint. for (GenericCapability capability : candidates) { @@ -1351,7 +1355,7 @@ public class ResolverImpl implements Resolver { } List<ResolverBundle> bundles = resolverBundles.get(req.getVersionConstraint().getName()); List<ResolverBundle> candidates = new ArrayList<ResolverBundle>(bundles); - List<Capability> capabilities = new ArrayList<Capability>(candidates.size()); + List<BundleCapability> capabilities = new ArrayList<BundleCapability>(candidates.size()); // Must remove candidates that do not match before calling hooks. for (Iterator<ResolverBundle> iCandidates = candidates.iterator(); iCandidates.hasNext();) { ResolverBundle bundle = iCandidates.next(); @@ -1362,7 +1366,7 @@ public class ResolverImpl implements Resolver { } } if (hook != null) - hook.filterMatches(req.getBundle().getBundleDescription(), asCapabilities(new ArrayMap<Capability, ResolverBundle>(capabilities, candidates))); + hook.filterMatches(req.getRequirement(), asCapabilities(new ArrayMap<BundleCapability, ResolverBundle>(capabilities, candidates))); // We are left with only capabilities that satisfy the require bundle. boolean result = false; for (ResolverBundle bundle : candidates) { @@ -1418,7 +1422,7 @@ public class ResolverImpl implements Resolver { ResolverExport[] substitutableExps = imp.getBundle().getExports(imp.getName()); List<ResolverExport> exports = resolverExports.get(imp.getName()); List<ResolverExport> candidates = new ArrayList<ResolverExport>(exports); - List<Capability> capabilities = new ArrayList<Capability>(candidates.size()); + List<BundleCapability> capabilities = new ArrayList<BundleCapability>(candidates.size()); // Must remove candidates that do not match before calling hooks. for (Iterator<ResolverExport> iCandidates = candidates.iterator(); iCandidates.hasNext();) { ResolverExport export = iCandidates.next(); @@ -1429,7 +1433,7 @@ public class ResolverImpl implements Resolver { } } if (hook != null) - hook.filterMatches(imp.getBundle().getBundleDescription(), asCapabilities(new ArrayMap<Capability, ResolverExport>(capabilities, candidates))); + hook.filterMatches(imp.getRequirement(), asCapabilities(new ArrayMap<BundleCapability, ResolverExport>(capabilities, candidates))); // We are left with only capabilities that satisfy the import. for (ResolverExport export : candidates) { if (DEBUG_IMPORTS) @@ -1583,6 +1587,10 @@ public class ResolverImpl implements Resolver { stateResolveFragConstraints(rb); else stateResolveConstraints(rb); + + // Build up the state wires + Map<String, List<StateWire>> stateWires = new HashMap<String, List<StateWire>>(); + // Gather selected exports ResolverExport[] exports = rb.getSelectedExports(); List<ExportPackageDescription> selectedExports = new ArrayList<ExportPackageDescription>(exports.length); @@ -1601,15 +1609,22 @@ public class ResolverImpl implements Resolver { ExportPackageDescription[] substitutedExportsArray = substitutedExports.toArray(new ExportPackageDescription[substitutedExports.size()]); // Gather exports that have been wired to - ExportPackageDescription[] exportsWiredToArray = getExportsWiredTo(rb); + ExportPackageDescription[] exportsWiredToArray = getExportsWiredTo(rb, stateWires); // Gather bundles that have been wired to BundleConstraint[] requires = rb.getRequires(); List<BundleDescription> bundlesWiredTo = new ArrayList<BundleDescription>(requires.length); + List<StateWire> requireWires = new ArrayList<StateWire>(requires.length); for (int i = 0; i < requires.length; i++) - if (requires[i].getSelectedSupplier() != null) - bundlesWiredTo.add((BundleDescription) requires[i].getSelectedSupplier().getBaseDescription()); + if (requires[i].getSelectedSupplier() != null) { + BundleDescription supplier = (BundleDescription) requires[i].getSelectedSupplier().getBaseDescription(); + bundlesWiredTo.add(supplier); + StateWire requireWire = newStateWire(rb.getBundleDescription(), requires[i].getVersionConstraint(), supplier, supplier); + requireWires.add(requireWire); + } BundleDescription[] bundlesWiredToArray = bundlesWiredTo.toArray(new BundleDescription[bundlesWiredTo.size()]); + if (!requireWires.isEmpty()) + stateWires.put(BundleRevision.BUNDLE_NAMESPACE, requireWires); GenericCapability[] capabilities = rb.getGenericCapabilities(); List<GenericDescription> selectedCapabilities = new ArrayList<GenericDescription>(capabilities.length); @@ -1623,8 +1638,17 @@ public class ResolverImpl implements Resolver { for (GenericConstraint genericConstraint : genericRequires) { VersionSupplier[] matching = genericConstraint.getMatchingCapabilities(); if (matching != null) - for (VersionSupplier capability : matching) - resolvedGenericRequires.add(((GenericCapability) capability).getGenericDescription()); + for (VersionSupplier capability : matching) { + GenericDescription supplier = ((GenericCapability) capability).getGenericDescription(); + resolvedGenericRequires.add(supplier); + StateWire genericWire = newStateWire(rb.getBundleDescription(), genericConstraint.getVersionConstraint(), supplier.getSupplier(), supplier); + List<StateWire> genericWires = stateWires.get(genericConstraint.getNameSpace()); + if (genericWires == null) { + genericWires = new ArrayList<StateWire>(); + stateWires.put(genericConstraint.getNameSpace(), genericWires); + } + genericWires.add(genericWire); + } } GenericDescription[] capabilitiesWiredToArray = resolvedGenericRequires.toArray(new GenericDescription[resolvedGenericRequires.size()]); @@ -1633,8 +1657,12 @@ public class ResolverImpl implements Resolver { VersionSupplier[] matchingBundles = rb.getHost().getPossibleSuppliers(); if (matchingBundles != null && matchingBundles.length > 0) { hostBundles = new BundleDescription[matchingBundles.length]; + List<StateWire> hostWires = new ArrayList<StateWire>(matchingBundles.length); + stateWires.put(BundleRevision.HOST_NAMESPACE, hostWires); for (int i = 0; i < matchingBundles.length; i++) { hostBundles[i] = matchingBundles[i].getBundleDescription(); + StateWire hostWire = newStateWire(rb.getBundleDescription(), rb.getHost().getVersionConstraint(), hostBundles[i], hostBundles[i]); + hostWires.add(hostWire); if (hostBundles[i].isResolved()) { ExportPackageDescription[] newSelectedExports = null; GenericDescription[] newSelectedCapabilities = null; @@ -1657,7 +1685,7 @@ public class ResolverImpl implements Resolver { newSelectedCapabilities = hostBundles[i].getSelectedGenericCapabilities(); if (newSelectedExports == null) newSelectedExports = hostBundles[i].getSelectedExports(); - state.resolveBundle(hostBundles[i], true, null, newSelectedExports, hostBundles[i].getSubstitutedExports(), newSelectedCapabilities, hostBundles[i].getResolvedRequires(), hostBundles[i].getResolvedImports(), hostBundles[i].getResolvedGenericRequires()); + state.resolveBundle(hostBundles[i], true, null, newSelectedExports, hostBundles[i].getSubstitutedExports(), newSelectedCapabilities, hostBundles[i].getResolvedRequires(), hostBundles[i].getResolvedImports(), hostBundles[i].getResolvedGenericRequires(), ((BundleDescriptionImpl) hostBundles[i]).getWires()); } } } @@ -1665,19 +1693,32 @@ public class ResolverImpl implements Resolver { } // Resolve the bundle in the state - state.resolveBundle(rb.getBundleDescription(), rb.isResolved(), hostBundles, selectedExportsArray, substitutedExportsArray, selectedCapabilitiesArray, bundlesWiredToArray, exportsWiredToArray, capabilitiesWiredToArray); + state.resolveBundle(rb.getBundleDescription(), rb.isResolved(), hostBundles, selectedExportsArray, substitutedExportsArray, selectedCapabilitiesArray, bundlesWiredToArray, exportsWiredToArray, capabilitiesWiredToArray, stateWires); } - private static ExportPackageDescription[] getExportsWiredTo(ResolverBundle rb) { + private static ExportPackageDescription[] getExportsWiredTo(ResolverBundle rb, Map<String, List<StateWire>> stateWires) { // Gather exports that have been wired to ResolverImport[] imports = rb.getImportPackages(); List<ExportPackageDescription> exportsWiredTo = new ArrayList<ExportPackageDescription>(imports.length); + List<StateWire> importWires = new ArrayList<StateWire>(imports.length); for (int i = 0; i < imports.length; i++) - if (imports[i].getSelectedSupplier() != null) - exportsWiredTo.add((ExportPackageDescription) imports[i].getSelectedSupplier().getBaseDescription()); + if (imports[i].getSelectedSupplier() != null) { + ExportPackageDescription supplier = (ExportPackageDescription) imports[i].getSelectedSupplier().getBaseDescription(); + exportsWiredTo.add(supplier); + StateWire wire = newStateWire(rb.getBundleDescription(), imports[i].getVersionConstraint(), supplier.getExporter(), supplier); + importWires.add(wire); + } + if (stateWires != null && !importWires.isEmpty()) + stateWires.put(BundleRevision.PACKAGE_NAMESPACE, importWires); return exportsWiredTo.toArray(new ExportPackageDescription[exportsWiredTo.size()]); } + private static StateWire newStateWire(BundleDescription requirementHost, VersionConstraint declaredRequirement, BundleDescription capabilityHost, BaseDescription declaredCapability) { + BaseDescription fragDeclared = ((BaseDescriptionImpl) declaredCapability).getFragmentDeclaration(); + declaredCapability = fragDeclared != null ? fragDeclared : declaredCapability; + return new StateWire(requirementHost, declaredRequirement, capabilityHost, declaredCapability); + } + // Resolve dynamic import public synchronized ExportPackageDescription resolveDynamicImport(BundleDescription importingBundle, String requestedPackage) { if (state == null) @@ -1720,6 +1761,16 @@ public class ResolverImpl implements Resolver { } } + private void addStateWire(BundleDescription importingBundle, VersionConstraint requirement, BundleDescription capabilityHost, ExportPackageDescription capability) { + Map<String, List<StateWire>> wires = ((BundleDescriptionImpl) importingBundle).getWires(); + List<StateWire> imports = wires.get(BundleRevision.PACKAGE_NAMESPACE); + if (imports == null) { + imports = new ArrayList<StateWire>(); + wires.put(BundleRevision.PACKAGE_NAMESPACE, imports); + } + imports.add(newStateWire(importingBundle, requirement, capabilityHost, capability)); + } + private ExportPackageDescription resolveDynamicImport(ResolverImport dynamicImport, String requestedPackage) { String importName = dynamicImport.getName(); // If the import uses a wildcard, then temporarily replace this with the requested package @@ -1742,7 +1793,11 @@ public class ResolverImpl implements Resolver { // If the import resolved then return it's matching export if (DEBUG_IMPORTS) ResolverImpl.log("Resolved dynamic import: " + dynamicImport.getBundle() + ":" + dynamicImport.getName() + " -> " + ((ResolverExport) dynamicImport.getSelectedSupplier()).getExporter() + ":" + requestedPackage); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ - return ((ResolverExport) dynamicImport.getSelectedSupplier()).getExportPackageDescription(); + + ExportPackageDescription supplier = ((ResolverExport) dynamicImport.getSelectedSupplier()).getExportPackageDescription(); + if (supplier != null) + addStateWire(dynamicImport.getBundleDescription(), dynamicImport.getVersionConstraint(), supplier.getExporter(), supplier); + return supplier; } } dynamicImport.clearPossibleSuppliers(); @@ -1833,7 +1888,7 @@ public class ResolverImpl implements Resolver { setBundleUnresolved(bundle, removed, false); // Get bundles dependent on 'bundle' BundleDescription[] dependents = bundle.getBundleDescription().getDependents(); - state.resolveBundle(bundle.getBundleDescription(), false, null, null, null, null, null, null, null); + state.resolveBundle(bundle.getBundleDescription(), false, null, null, null, null, null, null, null, null); // Unresolve dependents of 'bundle' for (int i = 0; i < dependents.length; i++) unresolveBundle(bundleMapping.get(dependents[i]), false); diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java index 6b7be54b6..b27b03876 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionHashMap.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 IBM Corporation and others. + * Copyright (c) 2004, 2011 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 @@ -78,7 +78,7 @@ public class VersionHashMap<V extends VersionSupplier> extends MappedList<String void reorder() { for (Iterator<List<V>> it = internal.values().iterator(); it.hasNext();) { List<V> existing = it.next(); - if (existing.size() > 0) + if (existing.size() > 1) Collections.sort(existing, this); } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionSupplier.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionSupplier.java index 9ffdaeb91..03c94b021 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionSupplier.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/module/VersionSupplier.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2008 IBM Corporation and others. + * Copyright (c) 2004, 2011 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 @@ -13,14 +13,14 @@ package org.eclipse.osgi.internal.module; import org.eclipse.osgi.service.resolver.BaseDescription; import org.eclipse.osgi.service.resolver.BundleDescription; import org.osgi.framework.Version; -import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.BundleCapability; /* * A companion to BaseDescription from the state used while resolving. */ public abstract class VersionSupplier { final protected BaseDescription base; - final private Capability capability; + final private BundleCapability capability; private VersionSupplier substitute; VersionSupplier(BaseDescription base) { @@ -65,7 +65,7 @@ public abstract class VersionSupplier { return base.toString(); } - Capability getCapability() { + BundleCapability getCapability() { return capability; } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java index 5d890cf3f..c158d325f 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BaseDescriptionImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 IBM Corporation and others. + * Copyright (c) 2004, 2011 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 @@ -13,11 +13,11 @@ package org.eclipse.osgi.internal.resolver; import java.util.*; import org.eclipse.osgi.service.resolver.BaseDescription; -import org.eclipse.osgi.service.resolver.BundleDescription; import org.osgi.framework.Version; -import org.osgi.framework.wiring.*; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleRevision; -abstract class BaseDescriptionImpl implements BaseDescription { +public abstract class BaseDescriptionImpl implements BaseDescription { protected final Object monitor = new Object(); @@ -84,24 +84,18 @@ abstract class BaseDescriptionImpl implements BaseDescription { return null; } - WiredCapability getWiredCapability(String namespace) { - if (namespace == null) - namespace = getInternalNameSpace(); - if (namespace == null) - return null; - - BundleDescription supplier = getSupplier(); - BundleWiring wiring = supplier.getBundleWiring(); - if (wiring == null) - return null; - return new BaseWiredCapability(namespace, wiring); + public BaseDescription getFragmentDeclaration() { + return null; } - public Capability getCapability() { + public BundleCapability getCapability() { return getCapability(null); } - Capability getCapability(String namespace) { + BundleCapability getCapability(String namespace) { + BaseDescriptionImpl fragmentDeclaration = (BaseDescriptionImpl) getFragmentDeclaration(); + if (fragmentDeclaration != null) + return fragmentDeclaration.getCapability(namespace); if (namespace == null) namespace = getInternalNameSpace(); if (namespace == null) @@ -109,7 +103,7 @@ abstract class BaseDescriptionImpl implements BaseDescription { return new BaseCapability(namespace); } - class BaseCapability implements Capability { + class BaseCapability implements BundleCapability { private final String namespace; public BaseCapability(String namespace) { @@ -117,7 +111,7 @@ abstract class BaseDescriptionImpl implements BaseDescription { this.namespace = namespace; } - public BundleRevision getProviderRevision() { + public BundleRevision getRevision() { return getSupplier(); } @@ -162,61 +156,4 @@ abstract class BaseDescriptionImpl implements BaseDescription { return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false); } } - - class BaseWiredCapability extends BaseCapability implements WiredCapability { - private final BundleWiring originalWiring; - - public BaseWiredCapability(String namespace, BundleWiring originalWiring) { - super(namespace); - this.originalWiring = originalWiring; - } - - public Collection<BundleWiring> getRequirerWirings() { - BundleWiring wiring = getProviderWiring(); - if (wiring == null) - return null; - BundleDescription supplier = getSupplier(); - BundleDescription[] dependents = supplier.getDependents(); - Collection<BundleWiring> requirers = new ArrayList<BundleWiring>(); - if (Capability.HOST_CAPABILITY.equals(getNamespace())) { - // special casing osgi.host capability. - // this is needed because the host capability is manufactured only for - // representation in the wiring API. We need to represent a host wiring - // as requiring its own osgi.host capability if it has attached fragments - List<BundleRevision> fragments = wiring.getFragmentRevisions(); - if (fragments != null && fragments.size() > 0) - // found at least one fragment add the host wiring as a requirer and return - requirers.add(wiring); - } - - for (BundleDescription dependent : dependents) { - BundleWiring dependentWiring = dependent.getBundleWiring(); - if (dependentWiring == null) // fragments have no wiring - continue; - List<WiredCapability> namespace = dependentWiring.getRequiredCapabilities(getNamespace()); - if (namespace == null) - continue; - if (namespace.contains(this)) - requirers.add(dependentWiring); - } - return requirers; - } - - public BundleWiring getProviderWiring() { - return originalWiring.isInUse() ? originalWiring : null; - } - - public int hashCode() { - return System.identityHashCode(BaseDescriptionImpl.this) ^ System.identityHashCode(originalWiring); - } - - public boolean equals(Object obj) { - if (this == obj) - return true; - if (!(obj instanceof BaseWiredCapability)) - return false; - BaseWiredCapability other = (BaseWiredCapability) obj; - return (other.originalWiring == this.originalWiring) && super.equals(obj); - } - } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java index a3ab615f6..efcc81c76 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleDescriptionImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -47,7 +47,7 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements private volatile int stateBits = FULLY_LOADED | ATTACH_FRAGMENTS | DYNAMIC_FRAGMENTS; private volatile long bundleId = -1; - private volatile HostSpecification host; //null if the bundle is not a fragment. volatile to allow unsynchronized checks for null + volatile HostSpecification host; //null if the bundle is not a fragment. volatile to allow unsynchronized checks for null private volatile StateImpl containingState; private volatile Object userObject; @@ -257,6 +257,23 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements } } + public Map<String, List<StateWire>> getWires() { + LazyData currentData = loadLazyData(); + synchronized (this.monitor) { + if (currentData.stateWires == null) { + currentData.stateWires = new HashMap<String, List<StateWire>>(0); + } + return currentData.stateWires; + } + } + + Map<String, List<StateWire>> getWiresInternal() { + LazyData currentData = loadLazyData(); + synchronized (this.monitor) { + return currentData.stateWires; + } + } + protected void setBundleId(long bundleId) { this.bundleId = bundleId; } @@ -461,6 +478,13 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements } } + protected void setStateWires(Map<String, List<StateWire>> stateWires) { + synchronized (this.monitor) { + checkLazyData(); + lazyData.stateWires = stateWires; + } + } + void clearAddedDynamicImportPackages() { synchronized (this.monitor) { checkLazyData(); @@ -792,6 +816,7 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements String[] executionEnvironments; Map<String, Long> dynamicStamps; + Map<String, List<StateWire>> stateWires; // Note that this is not persisted in the state cache List<ImportPackageSpecification> addedDynamicImports; } @@ -856,37 +881,61 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements if (attributes != null) result.putAll(attributes); } - result.put(Capability.BUNDLE_CAPABILITY, getName()); + result.put(BundleRevision.BUNDLE_NAMESPACE, getName()); result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, getVersion()); return Collections.unmodifiableMap(result); } - public List<Capability> getDeclaredCapabilities(String namespace) { - List<Capability> result = new ArrayList<Capability>(); + public List<BundleRequirement> getDeclaredRequirements(String namespace) { + List<BundleRequirement> result = new ArrayList<BundleRequirement>(); + if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { + BundleSpecification[] requires = getRequiredBundles(); + for (BundleSpecification require : requires) { + result.add(require.getRequirement()); + } + } + if (host != null && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { + result.add(host.getRequirement()); + } + if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { + ImportPackageSpecification[] imports = getImportPackages(); + for (ImportPackageSpecification importPkg : imports) + result.add(importPkg.getRequirement()); + } + GenericSpecification[] genericSpecifications = getGenericRequires(); + for (GenericSpecification requirement : genericSpecifications) { + if (namespace == null || namespace.equals(requirement.getType())) + result.add(requirement.getRequirement()); + } + return Collections.unmodifiableList(result); + } + + public List<BundleCapability> getDeclaredCapabilities(String namespace) { + List<BundleCapability> result = new ArrayList<BundleCapability>(); if (host == null) { if (getSymbolicName() != null) { - if (namespace == null || Capability.BUNDLE_CAPABILITY.equals(namespace)) { + if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { result.add(BundleDescriptionImpl.this.getCapability()); } - if (attachFragments() && (namespace == null || Capability.HOST_CAPABILITY.equals(namespace))) { - result.add(BundleDescriptionImpl.this.getCapability(Capability.HOST_CAPABILITY)); + if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { + result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE)); } } } else { - // may need to have a osgi.fragment capability + // may need to have a osgi.wiring.fragment capability } - if (namespace == null || Capability.PACKAGE_CAPABILITY.equals(namespace)) { + if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { ExportPackageDescription[] exports = getExportPackages(); - for (ExportPackageDescription importPkg : exports) - result.add(importPkg.getCapability()); + for (ExportPackageDescription exportPkg : exports) + result.add(exportPkg.getCapability()); } GenericDescription[] genericCapabilities = getGenericCapabilities(); for (GenericDescription capabilitiy : genericCapabilities) { if (namespace == null || namespace.equals(capabilitiy.getType())) result.add(capabilitiy.getCapability()); } - return result; + return Collections.unmodifiableList(result); } public int getTypes() { @@ -901,17 +950,72 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements } String getInternalNameSpace() { - return Capability.BUNDLE_CAPABILITY; + return BundleRevision.BUNDLE_NAMESPACE; } - public BundleWiring getBundleWiring() { + public BundleWiring getWiring() { synchronized (this.monitor) { - if (bundleWiring != null || !isResolved() || (getTypes() & BundleRevision.TYPE_FRAGMENT) != 0) + if (bundleWiring != null || !isResolved()) return bundleWiring; return bundleWiring = new DescriptionWiring(); } } + static class BundleWireImpl implements BundleWire { + private final BundleCapability capability; + private final BundleWiring provider; + private final BundleRequirement requirement; + private final BundleWiring requirer; + + public BundleWireImpl(StateWire wire) { + VersionConstraint declaredRequirement = wire.getDeclaredRequirement(); + if (declaredRequirement instanceof HostSpecification) + this.capability = ((BaseDescriptionImpl) wire.getDeclaredCapability()).getCapability(BundleRevision.HOST_NAMESPACE); + else + this.capability = wire.getDeclaredCapability().getCapability(); + this.provider = wire.getCapabilityHost().getWiring(); + this.requirement = declaredRequirement.getRequirement(); + this.requirer = wire.getRequirementHost().getWiring(); + } + + public BundleCapability getCapability() { + return capability; + } + + public BundleRequirement getRequirement() { + return requirement; + } + + public BundleWiring getProviderWiring() { + return provider; + } + + public BundleWiring getRequirerWiring() { + return requirer; + } + + @Override + public int hashCode() { + int hashcode = 31 + capability.hashCode(); + hashcode = hashcode * 31 + requirement.hashCode(); + hashcode = hashcode * 31 + provider.hashCode(); + hashcode = hashcode * 31 + requirer.hashCode(); + return hashcode; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof BundleWireImpl)) + return false; + BundleWireImpl other = (BundleWireImpl) obj; + return capability.equals(other.getCapability()) && requirement.equals(other.getRequirement()) && provider.equals(other.getProviderWiring()) && requirer.equals(other.getRequirerWiring()); + } + + public String toString() { + return getRequirement() + " -> " + getCapability(); //$NON-NLS-1$ + } + } + // Note that description wiring are identity equality based class DescriptionWiring implements BundleWiring { private volatile boolean valid = true; @@ -932,69 +1036,115 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements return valid && !BundleDescriptionImpl.this.isRemovalPending(); } - public List<WiredCapability> getRequiredCapabilities(String capabilityNamespace) { + public List<BundleCapability> getCapabilities(String namespace) { if (!isInUse()) return null; - List<WiredCapability> result = new ArrayList<WiredCapability>(); - if (capabilityNamespace == null || Capability.BUNDLE_CAPABILITY.equals(capabilityNamespace)) { - BundleDescription[] requires = getResolvedRequires(); - for (BundleDescription require : requires) - result.add(((BaseDescriptionImpl) require).getWiredCapability(null)); - } - if (attachFragments() && (capabilityNamespace == null || Capability.HOST_CAPABILITY.equals(capabilityNamespace))) { - Collection<BundleRevision> fragments = getFragmentRevisions(); - if (fragments.size() > 0) - result.add(BundleDescriptionImpl.this.getWiredCapability(Capability.HOST_CAPABILITY)); + @SuppressWarnings("unchecked") + List<BundleCapability> result = Collections.EMPTY_LIST; + if (host != null) + return result; + result = new ArrayList<BundleCapability>(); + if (getSymbolicName() != null) { + if (namespace == null || BundleRevision.BUNDLE_NAMESPACE.equals(namespace)) { + result.add(BundleDescriptionImpl.this.getCapability()); + } + if (attachFragments() && (namespace == null || BundleRevision.HOST_NAMESPACE.equals(namespace))) { + result.add(BundleDescriptionImpl.this.getCapability(BundleRevision.HOST_NAMESPACE)); + } } - if (capabilityNamespace == null || Capability.PACKAGE_CAPABILITY.equals(capabilityNamespace)) { - ExportPackageDescription[] imports = getResolvedImports(); - for (ExportPackageDescription importPkg : imports) - result.add(((BaseDescriptionImpl) importPkg).getWiredCapability(null)); + if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { + ExportPackageDescription[] exports = getSelectedExports(); + for (ExportPackageDescription exportPkg : exports) + result.add(exportPkg.getCapability()); } - GenericDescription[] genericRequires = getResolvedGenericRequires(); - for (GenericDescription require : genericRequires) { - if (capabilityNamespace == null || capabilityNamespace.equals(require.getType())) - result.add(((BaseDescriptionImpl) require).getWiredCapability(null)); + GenericDescription[] genericCapabilities = getSelectedGenericCapabilities(); + for (GenericDescription capabilitiy : genericCapabilities) { + if (namespace == null || namespace.equals(capabilitiy.getType())) + result.add(capabilitiy.getCapability()); } return result; } - public List<WiredCapability> getProvidedCapabilities(String capabilityNamespace) { - if (!isInUse()) + public List<BundleRequirement> getRequirements(String namespace) { + List<BundleWire> requiredWires = getRequiredWires(namespace); + if (requiredWires == null) + // happens if not in use return null; - List<WiredCapability> result = new ArrayList<WiredCapability>(); - if (getSymbolicName() != null) { - if ((capabilityNamespace == null || Capability.BUNDLE_CAPABILITY.equals(capabilityNamespace))) - result.add(BundleDescriptionImpl.this.getWiredCapability(null)); - if (attachFragments() && (capabilityNamespace == null || Capability.HOST_CAPABILITY.endsWith(capabilityNamespace))) - result.add(BundleDescriptionImpl.this.getWiredCapability(Capability.HOST_CAPABILITY)); + List<BundleRequirement> requirements = new ArrayList<BundleRequirement>(requiredWires.size()); + for (BundleWire wire : requiredWires) { + if (!requirements.contains(wire.getRequirement())) + requirements.add(wire.getRequirement()); + } + // get dynamic imports + if (namespace == null || BundleRevision.PACKAGE_NAMESPACE.equals(namespace)) { + if (hasDynamicImports()) { + ImportPackageSpecification[] imports = getImportPackages(); + for (ImportPackageSpecification impPackage : imports) { + if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(impPackage.getDirective(Constants.RESOLUTION_DIRECTIVE))) { + BundleRequirement req = impPackage.getRequirement(); + if (!requirements.contains(req)) + requirements.add(req); + } + } + } } + return requirements; + } - if (capabilityNamespace == null || Capability.PACKAGE_CAPABILITY.equals(capabilityNamespace)) { - ExportPackageDescription[] exports = getSelectedExports(); - for (ExportPackageDescription importPkg : exports) - result.add(((BaseDescriptionImpl) importPkg).getWiredCapability(null)); + public List<BundleWire> getProvidedWires(String namespace) { + if (!isInUse()) + return null; + BundleDescription[] dependentBundles = getDependents(); + List<BundleWire> unorderedResult = new ArrayList<BundleWire>(); + for (BundleDescription dependent : dependentBundles) { + List<BundleWire> dependentWires = dependent.getWiring().getRequiredWires(namespace); + if (dependentWires != null) + for (BundleWire bundleWire : dependentWires) { + if (bundleWire.getProviderWiring() == this) + unorderedResult.add(bundleWire); + } } - GenericDescription[] genericCapabilities = getSelectedGenericCapabilities(); - for (GenericDescription capabilitiy : genericCapabilities) { - if (capabilityNamespace == null || capabilityNamespace.equals(capabilitiy.getType())) - result.add(((BaseDescriptionImpl) capabilitiy).getWiredCapability(null)); + List<BundleWire> orderedResult = new ArrayList<BundleWire>(unorderedResult.size()); + List<BundleCapability> capabilities = getCapabilities(namespace); + for (BundleCapability capability : capabilities) { + for (Iterator<BundleWire> wires = unorderedResult.iterator(); wires.hasNext();) { + BundleWire wire = wires.next(); + if (wire.getCapability().equals(capability)) { + wires.remove(); + orderedResult.add(wire); + } + } } - return result; + return orderedResult; } - public List<BundleRevision> getFragmentRevisions() { + public List<BundleWire> getRequiredWires(String namespace) { if (!isInUse()) return null; - List<BundleRevision> results = new ArrayList<BundleRevision>(); - BundleDescription[] deps = getDependents(); - for (BundleDescription dependent : deps) { - if (dependent.getHost() != null) { - // found a fragment - results.add(dependent); + @SuppressWarnings("unchecked") + List<BundleWire> result = Collections.EMPTY_LIST; + Map<String, List<StateWire>> wireMap = getWires(); + if (namespace == null) { + result = new ArrayList<BundleWire>(); + for (List<StateWire> wires : wireMap.values()) { + for (StateWire wire : wires) { + result.add(new BundleWireImpl(wire)); + } } + return result; + } + List<StateWire> wires = wireMap.get(namespace); + if (wires == null) + return result; + result = new ArrayList<BundleWire>(wires.size()); + for (StateWire wire : wires) { + result.add(new BundleWireImpl(wire)); } - return results; + return result; + } + + public BundleRevision getRevision() { + return BundleDescriptionImpl.this; } public ClassLoader getClassLoader() { @@ -1019,10 +1169,6 @@ public final class BundleDescriptionImpl extends BaseDescriptionImpl implements return null; } - public BundleRevision getBundleRevision() { - return BundleDescriptionImpl.this; - } - private boolean hasResourcePermission() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java index 01e350b36..630313186 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/BundleSpecificationImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2008 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -11,10 +11,10 @@ *******************************************************************************/ package org.eclipse.osgi.internal.resolver; -import java.util.Map; -import org.eclipse.osgi.service.resolver.BaseDescription; -import org.eclipse.osgi.service.resolver.BundleSpecification; +import java.util.*; +import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.Constants; +import org.osgi.framework.wiring.BundleRevision; public class BundleSpecificationImpl extends VersionConstraintImpl implements BundleSpecification { private boolean exported; @@ -93,4 +93,36 @@ public class BundleSpecificationImpl extends VersionConstraintImpl implements Bu public String toString() { return "Require-Bundle: " + getName() + "; bundle-version=\"" + getVersionRange() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + + @Override + protected Map<String, String> getInternalDirectives() { + Map<String, String> result = new HashMap<String, String>(2); + synchronized (this.monitor) { + if (exported) + result.put(Constants.VISIBILITY_DIRECTIVE, Constants.VISIBILITY_REEXPORT); + if (optional) + result.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL); + return Collections.unmodifiableMap(result); + } + } + + @Override + protected Map<String, Object> getInteralAttributes() { + Map<String, Object> result = new HashMap<String, Object>(2); + synchronized (this.monitor) { + if (attributes != null) + result.putAll(attributes); + result.put(BundleRevision.BUNDLE_NAMESPACE, getName()); + VersionRange range = getVersionRange(); + if (range != null) + result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, range.toString()); + return Collections.unmodifiableMap(result); + } + } + + @Override + protected String getInternalNameSpace() { + // TODO Auto-generated method stub + return BundleRevision.BUNDLE_NAMESPACE; + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java index 6863b681a..a76444518 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ExportPackageDescriptionImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2010 IBM Corporation and others. + * Copyright (c) 2004, 2011 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 @@ -14,10 +14,9 @@ package org.eclipse.osgi.internal.resolver; import java.util.*; import org.eclipse.osgi.framework.internal.core.Constants; -import org.eclipse.osgi.service.resolver.BundleDescription; -import org.eclipse.osgi.service.resolver.ExportPackageDescription; +import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.Version; -import org.osgi.framework.wiring.Capability; +import org.osgi.framework.wiring.BundleRevision; public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements ExportPackageDescription { public static final String EQUINOX_EE = "x-equinox-ee"; //$NON-NLS-1$ @@ -31,7 +30,20 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements private String[] mandatory; private Boolean internal = Boolean.FALSE; private int equinox_ee = -1; - private volatile int tableIndex; + private ExportPackageDescription fragmentDeclaration = null; + + public ExportPackageDescriptionImpl() { + super(); + } + + public ExportPackageDescriptionImpl(BundleDescription host, ExportPackageDescription fragmentDeclaration) { + setName(fragmentDeclaration.getName()); + setVersion(fragmentDeclaration.getVersion()); + setDirectives(fragmentDeclaration.getDirectives()); + setAttributes(fragmentDeclaration.getAttributes()); + setExporter(host); + this.fragmentDeclaration = fragmentDeclaration; + } public Map<String, Object> getDirectives() { synchronized (this.monitor) { @@ -76,7 +88,7 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements synchronized (this.monitor) { if (attributes != null) result.putAll(attributes); - result.put(Capability.PACKAGE_CAPABILITY, getName()); + result.put(BundleRevision.PACKAGE_NAMESPACE, getName()); result.put(Constants.VERSION_ATTRIBUTE, getVersion()); Version bundleVersion = getSupplier().getVersion(); if (bundleVersion != null) @@ -185,19 +197,19 @@ public class ExportPackageDescriptionImpl extends BaseDescriptionImpl implements this.exporter = exporter; } - public String toString() { - return "Export-Package: " + getName() + "; version=\"" + getVersion() + "\""; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ + public BaseDescription getFragmentDeclaration() { + return fragmentDeclaration; } - int getTableIndex() { - return tableIndex; + void setFragmentDeclaration(ExportPackageDescription fragmentDeclaration) { + this.fragmentDeclaration = fragmentDeclaration; } - void setTableIndex(int tableIndex) { - this.tableIndex = tableIndex; + public String toString() { + return "Export-Package: " + getName() + "; version=\"" + getVersion() + "\""; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ } String getInternalNameSpace() { - return Capability.PACKAGE_CAPABILITY; + return BundleRevision.PACKAGE_NAMESPACE; } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericDescriptionImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericDescriptionImpl.java index b53c563d9..9e438f033 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericDescriptionImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericDescriptionImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2010 IBM Corporation and others. + * Copyright (c) 2006, 2011 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 @@ -12,8 +12,7 @@ package org.eclipse.osgi.internal.resolver; import java.util.*; -import org.eclipse.osgi.service.resolver.BundleDescription; -import org.eclipse.osgi.service.resolver.GenericDescription; +import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.Constants; import org.osgi.framework.Version; @@ -22,6 +21,29 @@ public class GenericDescriptionImpl extends BaseDescriptionImpl implements Gener private volatile BundleDescription supplier; private volatile String type = GenericDescription.DEFAULT_TYPE; private Map<String, String> directives; + private GenericDescription fragmentDeclaration; + + public GenericDescriptionImpl() { + super(); + } + + public GenericDescriptionImpl(BundleDescription host, GenericDescription fragmentDeclaration) { + setType(fragmentDeclaration.getType()); + Dictionary<String, Object> origAttrs = fragmentDeclaration.getAttributes(); + if (origAttrs != null) { + Hashtable<String, Object> copyAttrs = new Hashtable<String, Object>(); + for (Enumeration<String> keys = origAttrs.keys(); keys.hasMoreElements();) { + String key = keys.nextElement(); + copyAttrs.put(key, origAttrs.get(key)); + } + setAttributes(copyAttrs); + } + Map<String, String> origDirectives = fragmentDeclaration.getDeclaredDirectives(); + Map<String, String> copyDirectives = new HashMap<String, String>(origDirectives); + setDirectives(copyDirectives); + setSupplier(host); + this.fragmentDeclaration = fragmentDeclaration; + } public Dictionary<String, Object> getAttributes() { synchronized (this.monitor) { @@ -113,4 +135,12 @@ public class GenericDescriptionImpl extends BaseDescriptionImpl implements Gener String getInternalNameSpace() { return getType(); } + + public BaseDescription getFragmentDeclaration() { + return fragmentDeclaration; + } + + void setFragmentDeclaration(GenericDescription fragmentDeclaration) { + this.fragmentDeclaration = fragmentDeclaration; + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java index c919258fa..2afacb7e5 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/GenericSpecificationImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2010 IBM Corporation and others. + * Copyright (c) 2006, 2011 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 @@ -11,6 +11,7 @@ *******************************************************************************/ package org.eclipse.osgi.internal.resolver; +import java.util.*; import org.eclipse.osgi.framework.internal.core.FilterImpl; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.*; @@ -127,4 +128,28 @@ public class GenericSpecificationImpl extends VersionConstraintImpl implements G this.suppliers = suppliers; } } + + @Override + protected Map<String, String> getInternalDirectives() { + Map<String, String> result = new HashMap<String, String>(2); + synchronized (this.monitor) { + if ((resolution & GenericSpecification.RESOLUTION_OPTIONAL) != 0) + result.put(Constants.RESOLUTION_DIRECTIVE, Constants.RESOLUTION_OPTIONAL); + if (matchingFilter != null) { + result.put(Constants.FILTER_DIRECTIVE, matchingFilter.toString()); + } + } + return Collections.unmodifiableMap(result); + } + + @SuppressWarnings("unchecked") + @Override + protected Map<String, Object> getInteralAttributes() { + return Collections.EMPTY_MAP; + } + + @Override + protected String getInternalNameSpace() { + return getType(); + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java index 527e77620..e433fa74c 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/HostSpecificationImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2008 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -12,9 +12,10 @@ package org.eclipse.osgi.internal.resolver; -import java.util.Map; +import java.util.*; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.Constants; +import org.osgi.framework.wiring.BundleRevision; public class HostSpecificationImpl extends VersionConstraintImpl implements HostSpecification { @@ -111,4 +112,28 @@ public class HostSpecificationImpl extends VersionConstraintImpl implements Host this.multihost = multihost; } } + + @SuppressWarnings("unchecked") + protected Map<String, String> getInternalDirectives() { + // TODO this does not handle extension directive; but we do not support bootclasspath anyway + return Collections.EMPTY_MAP; + } + + protected Map<String, Object> getInteralAttributes() { + Map<String, Object> result = new HashMap<String, Object>(2); + synchronized (this.monitor) { + if (attributes != null) + result.putAll(attributes); + result.put(BundleRevision.HOST_NAMESPACE, getName()); + VersionRange range = getVersionRange(); + if (range != null) + result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, range.toString()); + return Collections.unmodifiableMap(result); + } + } + + @Override + protected String getInternalNameSpace() { + return BundleRevision.HOST_NAMESPACE; + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java index edf3107e2..6d34edd7f 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ImportPackageSpecificationImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2008 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -15,6 +15,7 @@ package org.eclipse.osgi.internal.resolver; import java.util.*; import org.eclipse.osgi.framework.internal.core.Constants; import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.wiring.BundleRevision; public class ImportPackageSpecificationImpl extends VersionConstraintImpl implements ImportPackageSpecification { private String resolution = ImportPackageSpecification.RESOLUTION_STATIC; // the default is static @@ -182,4 +183,32 @@ public class ImportPackageSpecificationImpl extends VersionConstraintImpl implem public String toString() { return "Import-Package: " + getName() + "; version=\"" + getVersionRange() + "\""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } + + @SuppressWarnings({"unchecked", "rawtypes"}) + protected Map<String, String> getInternalDirectives() { + Map raw = getDirectives(); + return Collections.unmodifiableMap(raw); + } + + protected Map<String, Object> getInteralAttributes() { + Map<String, Object> result = new HashMap<String, Object>(2); + synchronized (this.monitor) { + if (attributes != null) + result.putAll(attributes); + result.put(BundleRevision.PACKAGE_NAMESPACE, getName()); + VersionRange range = getVersionRange(); + if (range != null) + result.put(Constants.VERSION_ATTRIBUTE, range.toString()); + if (symbolicName != null) + result.put(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE, symbolicName); + if (bundleVersionRange != null) + result.put(Constants.BUNDLE_VERSION_ATTRIBUTE, bundleVersionRange.toString()); + return Collections.unmodifiableMap(result); + } + } + + @Override + protected String getInternalNameSpace() { + return BundleRevision.PACKAGE_NAMESPACE; + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java index 9a808e8d5..ee15b9edd 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/NativeCodeSpecificationImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 IBM Corporation and others. + * Copyright (c) 2007, 2011 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 @@ -156,4 +156,19 @@ public class NativeCodeSpecificationImpl extends VersionConstraintImpl implement return sb.toString(); } + + @SuppressWarnings("unchecked") + protected Map<String, String> getInternalDirectives() { + return Collections.EMPTY_MAP; + } + + @SuppressWarnings("unchecked") + protected Map<String, Object> getInteralAttributes() { + return Collections.EMPTY_MAP; + } + + @Override + protected String getInternalNameSpace() { + return null; + } } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java index a1d91c352..d0bc359ae 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/ReadOnlyState.java @@ -12,8 +12,7 @@ *******************************************************************************/ package org.eclipse.osgi.internal.resolver; -import java.util.Collection; -import java.util.Dictionary; +import java.util.*; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.BundleException; import org.osgi.framework.Version; @@ -133,7 +132,7 @@ public final class ReadOnlyState implements State { throw new UnsupportedOperationException(); } - public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolveCapabilities) { + public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolvedCapabilities, Map<String, List<StateWire>> resolvedRequirements) { throw new UnsupportedOperationException(); } diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java index de1db0560..131d7dd67 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateHelperImpl.java @@ -17,8 +17,8 @@ import org.eclipse.osgi.internal.baseadaptor.ArrayMap; import org.eclipse.osgi.service.resolver.*; import org.osgi.framework.hooks.resolver.ResolverHook; import org.osgi.framework.hooks.resolver.ResolverHookFactory; +import org.osgi.framework.wiring.BundleCapability; import org.osgi.framework.wiring.BundleRevision; -import org.osgi.framework.wiring.Capability; /** * An implementation for the StateHelper API. Access to this implementation is @@ -125,7 +125,7 @@ public final class StateHelperImpl implements StateHelper { Collection<BaseDescription> satisfied = null; if (constraint instanceof BundleSpecification || constraint instanceof HostSpecification) { BundleDescription[] suppliers = state.getBundles(constraint.getName()); - satisfied = getPossibleCandidates(constraint, suppliers, constraint instanceof HostSpecification ? Capability.HOST_CAPABILITY : null, hook, false); + satisfied = getPossibleCandidates(constraint, suppliers, constraint instanceof HostSpecification ? BundleRevision.HOST_NAMESPACE : null, hook, false); } else if (constraint instanceof ImportPackageSpecification) { List<ExportPackageDescription> exports = packages.get(constraint.getName()); if (exports != null) @@ -194,7 +194,7 @@ public final class StateHelperImpl implements StateHelper { List<VersionConstraint> unsatisfied = new ArrayList<VersionConstraint>(); HostSpecification host = bundle.getHost(); if (host != null) - if (!host.isResolved() && !isBundleConstraintResolvable(host, Capability.HOST_CAPABILITY, hook)) + if (!host.isResolved() && !isBundleConstraintResolvable(host, BundleRevision.HOST_NAMESPACE, hook)) unsatisfied.add(host); BundleSpecification[] requiredBundles = bundle.getRequiredBundles(); for (int i = 0; i < requiredBundles.length; i++) @@ -214,11 +214,11 @@ public final class StateHelperImpl implements StateHelper { return unsatisfied.toArray(new VersionConstraint[unsatisfied.size()]); } - private ArrayMap<Capability, BaseDescription> asArrayMap(List<BaseDescription> descriptions, String namespace) { - List<Capability> capabilities = new ArrayList<Capability>(descriptions.size()); + private ArrayMap<BundleCapability, BaseDescription> asArrayMap(List<BaseDescription> descriptions, String namespace) { + List<BundleCapability> capabilities = new ArrayList<BundleCapability>(descriptions.size()); for (BaseDescription description : descriptions) capabilities.add(((BaseDescriptionImpl) description).getCapability(namespace)); - return new ArrayMap<Capability, BaseDescription>(capabilities, descriptions); + return new ArrayMap<BundleCapability, BaseDescription>(capabilities, descriptions); } private List<BaseDescription> getPossibleCandidates(VersionConstraint constraint, BaseDescription[] descriptions, String namespace, ResolverHook hook, boolean resolved) { @@ -227,7 +227,7 @@ public final class StateHelperImpl implements StateHelper { if ((!resolved || descriptions[i].getSupplier().isResolved()) && constraint.isSatisfiedBy(descriptions[i])) candidates.add(descriptions[i]); if (hook != null) - hook.filterMatches(constraint.getBundle(), asArrayMap(candidates, namespace)); + hook.filterMatches(constraint.getRequirement(), asArrayMap(candidates, namespace)); return candidates; } @@ -268,7 +268,7 @@ public final class StateHelperImpl implements StateHelper { * @see StateHelper */ public boolean isResolvable(HostSpecification specification) { - return isBundleConstraintResolvable(specification, Capability.HOST_CAPABILITY); + return isBundleConstraintResolvable(specification, BundleRevision.HOST_NAMESPACE); } /* diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java index beac95554..79d37c5bf 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateImpl.java @@ -139,7 +139,7 @@ public abstract class StateImpl implements State { try { resolving = true; resolverErrors.remove(existing); - resolveBundle(existing, false, null, null, null, null, null, null, null); + resolveBundle(existing, false, null, null, null, null, null, null, null, null); } finally { resolving = false; } @@ -311,10 +311,10 @@ public abstract class StateImpl implements State { * @deprecated */ public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports) { - resolveBundle(bundle, status, hosts, selectedExports, substitutedExports, null, resolvedRequires, resolvedImports, null); + resolveBundle(bundle, status, hosts, selectedExports, substitutedExports, null, resolvedRequires, resolvedImports, null, null); } - public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolveCapabilities) { + public void resolveBundle(BundleDescription bundle, boolean status, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolvedCapabilities, Map<String, List<StateWire>> resolvedWires) { synchronized (this.monitor) { if (!resolving) throw new IllegalStateException(); // TODO need error message here! @@ -333,12 +333,12 @@ public abstract class StateImpl implements State { resolvedBundles.remove(modifiable); modifiable.removeDependencies(); } - // to support develoment mode we will resolveConstraints even if the resolve status == false + // to support development mode we will resolveConstraints even if the resolve status == false // we only do this if the resolved constraints are not null if (selectedExports == null || resolvedRequires == null || resolvedImports == null) unresolveConstraints(modifiable); else - resolveConstraints(modifiable, hosts, selectedExports, substitutedExports, selectedCapabilities, resolvedRequires, resolvedImports, resolveCapabilities); + resolveConstraints(modifiable, hosts, selectedExports, substitutedExports, selectedCapabilities, resolvedRequires, resolvedImports, resolvedCapabilities, resolvedWires); } } @@ -351,7 +351,7 @@ public abstract class StateImpl implements State { } } - private void resolveConstraints(BundleDescriptionImpl bundle, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolvedCapabilities) { + private void resolveConstraints(BundleDescriptionImpl bundle, BundleDescription[] hosts, ExportPackageDescription[] selectedExports, ExportPackageDescription[] substitutedExports, GenericDescription[] selectedCapabilities, BundleDescription[] resolvedRequires, ExportPackageDescription[] resolvedImports, GenericDescription[] resolvedCapabilities, Map<String, List<StateWire>> resolvedWires) { HostSpecificationImpl hostSpec = (HostSpecificationImpl) bundle.getHost(); if (hostSpec != null) { if (hosts != null) { @@ -369,6 +369,7 @@ public abstract class StateImpl implements State { bundle.setSubstitutedExports(substitutedExports); bundle.setSelectedCapabilities(selectedCapabilities); bundle.setResolvedCapabilities(resolvedCapabilities); + bundle.setStateWires(resolvedWires); bundle.addDependencies(hosts, true); bundle.addDependencies(resolvedRequires, true); @@ -381,25 +382,6 @@ public abstract class StateImpl implements State { // there are issues here because the order in which fragments are resolved is not always the same ... } - // private void checkForSubstitutedExports(BundleDescriptionImpl bundle, ExportPackageDescription[] selectedExports) { - // ExportPackageDescription[] existingSubstitutes = bundle.getSubstitutedExports(); - // ExportPackageDescription[] declaredExports = bundle.getExportPackages(); - // ArrayList substitutes = new ArrayList(); - // for (int i = 0; i < declaredExports.length; i++) { - // boolean selected = false; - // for (int j = 0; !selected && j < selectedExports.length; j++) - // selected = declaredExports[i] == selectedExports[j]; - // if (!selected) - // substitutes.add(declaredExports[i]); - // } - // if (substitutes.size() > 0) { - // substitutes.ensureCapacity(substitutes.size() + existingSubstitutes.length); - // for (int i = 0; i < existingSubstitutes.length; i++) - // substitutes.add(0, existingSubstitutes[i]); - // bundle.setSubstitutedExports((ExportPackageDescription[]) substitutes.toArray(new ExportPackageDescription[substitutes.size()])); - // } - // } - private void unresolveConstraints(BundleDescriptionImpl bundle) { HostSpecificationImpl host = (HostSpecificationImpl) bundle.getHost(); if (host != null) @@ -411,6 +393,7 @@ public abstract class StateImpl implements State { bundle.setSubstitutedExports(null); bundle.setSelectedCapabilities(null); bundle.setResolvedCapabilities(null); + bundle.setStateWires(null); bundle.clearAddedDynamicImportPackages(); // remove the constraint suppliers diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java index ea1954ce3..f31405073 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -46,7 +46,7 @@ final class StateReader { private volatile int numBundles; private volatile boolean accessedFlag = false; - public static final byte STATE_CACHE_VERSION = 35; + public static final byte STATE_CACHE_VERSION = 36; public static final byte NULL = 0; public static final byte OBJECT = 1; public static final byte INDEX = 2; @@ -75,7 +75,10 @@ final class StateReader { } private Object getFromObjectTable(int index) { - return objectTable.get(new Integer(index)); + Object result = objectTable.get(new Integer(index)); + if (result == null) + throw new IllegalStateException("Expected to find an object at table index: " + index); //$NON-NLS-1$ + return result; } private boolean readState(StateImpl state, long expectedTimestamp) throws IOException { @@ -370,6 +373,10 @@ final class StateReader { result.setNativeCodeSpecification(readNativeCode(in)); + @SuppressWarnings("rawtypes") + Map raw = readMap(in); + result.setStateWires(raw); + result.setFullyLoaded(true); // set fully loaded before setting the dependencies // No need to add bundle dependencies for hosts, imports or requires; // This is done by readBundleDescription @@ -377,7 +384,14 @@ final class StateReader { } private BundleSpecificationImpl readBundleSpec(DataInputStream in) throws IOException { + byte tag = readTag(in); + if (tag == NULL) + return null; + if (tag == INDEX) + return (BundleSpecificationImpl) getFromObjectTable(in.readInt()); BundleSpecificationImpl result = new BundleSpecificationImpl(); + int tableIndex = in.readInt(); + addToObjectTable(result, tableIndex); readVersionConstraint(result, in); result.setSupplier(readBundleDescription(in)); result.setExported(in.readBoolean()); @@ -395,11 +409,11 @@ final class StateReader { ExportPackageDescriptionImpl exportPackageDesc = new ExportPackageDescriptionImpl(); int tableIndex = in.readInt(); addToObjectTable(exportPackageDesc, tableIndex); - exportPackageDesc.setTableIndex(tableIndex); readBaseDescription(exportPackageDesc, in); exportPackageDesc.setExporter(readBundleDescription(in)); exportPackageDesc.setAttributes(readMap(in)); exportPackageDesc.setDirectives(readMap(in)); + exportPackageDesc.setFragmentDeclaration(readExportPackageDesc(in)); return exportPackageDesc; } @@ -464,6 +478,9 @@ final class StateReader { case 6 : list.add(readVersion(in)); break; + case 7 : + list.add(readStateWire(in)); + break; default : throw new IOException("Invalid type: " + listType); //$NON-NLS-1$ } @@ -475,6 +492,39 @@ final class StateReader { return result; } + private Object readStateWire(DataInputStream in) throws IOException { + VersionConstraint requirement; + BundleDescription requirementHost; + BaseDescription capability; + BundleDescription capabilityHost; + + byte wireType = in.readByte(); + switch (wireType) { + case 0 : + requirement = readImportPackageSpec(in); + capability = readExportPackageDesc(in); + break; + case 1 : + requirement = readBundleSpec(in); + capability = readBundleDescription(in); + break; + case 2 : + requirement = readHostSpec(in); + capability = readBundleDescription(in); + break; + case 3 : + requirement = readGenericSpecification(in); + capability = readGenericDescription(in); + break; + default : + throw new IOException("Invalid wire type: " + wireType); //$NON-NLS-1$ + } + + requirementHost = readBundleDescription(in); + capabilityHost = readBundleDescription(in); + return new StateWire(requirementHost, requirement, capabilityHost, capability); + } + private String[] readList(DataInputStream in) throws IOException { int count = in.readInt(); if (count == 0) @@ -491,7 +541,14 @@ final class StateReader { } private ImportPackageSpecificationImpl readImportPackageSpec(DataInputStream in) throws IOException { + byte tag = readTag(in); + if (tag == NULL) + return null; + if (tag == INDEX) + return (ImportPackageSpecificationImpl) getFromObjectTable(in.readInt()); ImportPackageSpecificationImpl result = new ImportPackageSpecificationImpl(); + int tableIndex = in.readInt(); + addToObjectTable(result, tableIndex); readVersionConstraint(result, in); result.setSupplier(readExportPackageDesc(in)); result.setBundleSymbolicName(readString(in, false)); @@ -505,7 +562,11 @@ final class StateReader { byte tag = readTag(in); if (tag == NULL) return null; + if (tag == INDEX) + return (HostSpecificationImpl) getFromObjectTable(in.readInt()); HostSpecificationImpl result = new HostSpecificationImpl(); + int tableIndex = in.readInt(); + addToObjectTable(result, tableIndex); readVersionConstraint(result, in); int hostCount = in.readInt(); if (hostCount > 0) { @@ -542,11 +603,19 @@ final class StateReader { Map directives = readMap(in); if (directives != null) result.setDirectives(directives); + result.setFragmentDeclaration(readGenericDescription(in)); return result; } private GenericSpecification readGenericSpecification(DataInputStream in) throws IOException { + byte tag = readTag(in); + if (tag == NULL) + return null; + if (tag == INDEX) + return (GenericSpecification) getFromObjectTable(in.readInt()); GenericSpecificationImpl result = new GenericSpecificationImpl(); + int tableIndex = in.readInt(); + addToObjectTable(result, tableIndex); readVersionConstraint(result, in); result.setType(readString(in, false)); int num = in.readInt(); diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java index 72bc7c2a4..33e39e4de 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/StateWriter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -28,7 +28,7 @@ class StateWriter { // cached state. private final Map<Object, Integer> objectTable = new HashMap<Object, Integer>(); - private final List<BundleDescription> forcedWrite = new ArrayList<BundleDescription>(); + private final List<Object> forcedWrite = new ArrayList<Object>(); private int addToObjectTable(Object object) { Integer cur = objectTable.get(object); @@ -336,6 +336,7 @@ class StateWriter { writeNativeCode(bundle.getNativeCodeSpecification(), out); + writeMap(out, ((BundleDescriptionImpl) bundle).getWiresInternal()); // save the size of the lazy data ((BundleDescriptionImpl) bundle).setLazyDataSize(out.size() - dataStart); } @@ -347,6 +348,8 @@ class StateWriter { } private void writeBundleSpec(BundleSpecificationImpl bundle, DataOutputStream out) throws IOException { + if (writePrefix(bundle, out)) + return; writeVersionConstraint(bundle, out); writeBundleDescription((BundleDescription) bundle.getSupplier(), out, false); out.writeBoolean(bundle.isExported()); @@ -361,6 +364,7 @@ class StateWriter { writeBundleDescription(exportPackageDesc.getExporter(), out, false); writeMap(out, exportPackageDesc.getAttributes()); writeMap(out, exportPackageDesc.getDirectives()); + writeExportPackageDesc((ExportPackageDescriptionImpl) exportPackageDesc.getFragmentDeclaration(), out); } private void writeGenericDescription(GenericDescription description, DataOutputStream out) throws IOException { @@ -378,9 +382,12 @@ class StateWriter { writeMap(out, mapAttrs); Map<String, String> directives = description.getDeclaredDirectives(); writeMap(out, directives); + writeGenericDescription((GenericDescription) ((BaseDescriptionImpl) description).getFragmentDeclaration(), out); } private void writeGenericSpecification(GenericSpecification specification, DataOutputStream out) throws IOException { + if (writePrefix(specification, out)) + return; writeVersionConstraint(specification, out); writeStringOrNull(specification.getType() == GenericDescription.DEFAULT_TYPE ? null : specification.getType(), out); GenericDescription[] suppliers = specification.getSuppliers(); @@ -505,12 +512,45 @@ class StateWriter { case 6 : writeVersion((Version) value, out); break; + case 7 : + writeStateWire((StateWire) value, out); default : break; } } } + private void writeStateWire(StateWire wire, DataOutputStream out) throws IOException { + VersionConstraint requirement = wire.getDeclaredRequirement(); + if (requirement instanceof ImportPackageSpecificationImpl) { + out.writeByte(0); + writeImportPackageSpec((ImportPackageSpecificationImpl) requirement, out); + } else if (requirement instanceof BundleSpecificationImpl) { + out.writeByte(1); + writeBundleSpec((BundleSpecificationImpl) requirement, out); + } else if (requirement instanceof HostSpecificationImpl) { + out.writeByte(2); + writeHostSpec((HostSpecificationImpl) requirement, out, false); + } else if (requirement instanceof GenericSpecificationImpl) { + out.writeByte(3); + writeGenericSpecification((GenericSpecificationImpl) requirement, out); + } else + throw new IllegalArgumentException("Unknown requiement type: " + requirement.getClass()); + + BaseDescription capability = wire.getDeclaredCapability(); + if (capability instanceof BundleDescription) + writeBundleDescription((BundleDescription) capability, out, false); + else if (capability instanceof ExportPackageDescriptionImpl) + writeExportPackageDesc((ExportPackageDescriptionImpl) capability, out); + else if (capability instanceof GenericDescription) + writeGenericDescription((GenericDescription) capability, out); + else + throw new IllegalArgumentException("Unknown capability type: " + requirement.getClass()); + + writeBundleDescription(wire.getRequirementHost(), out, false); + writeBundleDescription(wire.getCapabilityHost(), out, false); + } + private byte getListType(List<?> list) { if (list.size() == 0) return -1; @@ -525,6 +565,8 @@ class StateWriter { return 5; if (type instanceof Version) return 6; + if (type instanceof StateWire) + return 7; return -2; } @@ -544,6 +586,8 @@ class StateWriter { } private void writeImportPackageSpec(ImportPackageSpecification importPackageSpec, DataOutputStream out) throws IOException { + if (writePrefix(importPackageSpec, out)) + return; writeVersionConstraint(importPackageSpec, out); // TODO this is a hack until the state dynamic loading is cleaned up // we should only write the supplier if we are resolved @@ -559,11 +603,13 @@ class StateWriter { } private void writeHostSpec(HostSpecificationImpl host, DataOutputStream out, boolean force) throws IOException { - if (host == null) { - out.writeByte(StateReader.NULL); + if (host != null && force && !forcedWrite.contains(host)) { + int index = addToObjectTable(host); + out.writeByte(StateReader.OBJECT); + out.writeInt(index); + forcedWrite.add(host); + } else if (writePrefix(host, out)) return; - } - out.writeByte(StateReader.OBJECT); writeVersionConstraint(host, out); BundleDescription[] hosts = host.getHosts(); if (hosts == null) { diff --git a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java index 5d668cb15..d3c8df191 100644 --- a/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java +++ b/bundles/org.eclipse.osgi/resolver/src/org/eclipse/osgi/internal/resolver/VersionConstraintImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2010 IBM Corporation and others. + * Copyright (c) 2003, 2011 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 @@ -12,8 +12,12 @@ *******************************************************************************/ package org.eclipse.osgi.internal.resolver; +import java.util.Collections; +import java.util.Map; import org.eclipse.osgi.framework.internal.core.Constants; +import org.eclipse.osgi.internal.resolver.BaseDescriptionImpl.BaseCapability; import org.eclipse.osgi.service.resolver.*; +import org.osgi.framework.wiring.*; abstract class VersionConstraintImpl implements VersionConstraint { @@ -89,4 +93,67 @@ abstract class VersionConstraintImpl implements VersionConstraint { this.supplier = supplier; } } + + protected abstract String getInternalNameSpace(); + + protected abstract Map<String, String> getInternalDirectives(); + + protected abstract Map<String, Object> getInteralAttributes(); + + public BundleRequirement getRequirement() { + String namespace = getInternalNameSpace(); + if (namespace == null) + return null; + return new BundleRequirementImpl(namespace); + } + + class BundleRequirementImpl implements BundleRequirement { + private final String namespace; + + public BundleRequirementImpl(String namespace) { + this.namespace = namespace; + } + + public String getNamespace() { + return namespace; + } + + @SuppressWarnings("unchecked") + public Map<String, String> getDirectives() { + return Collections.unmodifiableMap(getInternalDirectives()); + } + + @SuppressWarnings("unchecked") + public Map<String, Object> getAttributes() { + return getInteralAttributes(); + } + + public BundleRevision getRevision() { + return getBundle(); + } + + public boolean matches(BundleCapability capability) { + return isSatisfiedBy(((BaseCapability) capability).getBaseDescription()); + } + + public int hashCode() { + return System.identityHashCode(VersionConstraintImpl.this); + } + + private VersionConstraintImpl getVersionConstraint() { + return VersionConstraintImpl.this; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (!(obj instanceof BundleRequirementImpl)) + return false; + return ((BundleRequirementImpl) obj).getVersionConstraint() == VersionConstraintImpl.this; + } + + public String toString() { + return getNamespace() + BaseDescriptionImpl.toString(getAttributes(), false); + } + } } |