Initial pass at support for fragments exporting, importing, and requiring.
(FELIX-29)
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@770791 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
index 49291a9..5f17330 100644
--- a/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -732,6 +732,11 @@
public Class loadClass(String name) throws ClassNotFoundException
{
+ if (isExtension())
+ {
+ throw new ClassNotFoundException("Extension bundles cannot load classes.");
+ }
+
Object sm = System.getSecurityManager();
if (sm != null)
diff --git a/framework/src/main/java/org/apache/felix/framework/Felix.java b/framework/src/main/java/org/apache/felix/framework/Felix.java
index ccd86de..10c98cf 100644
--- a/framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -2176,7 +2176,14 @@
ex.printStackTrace();
- throw new BundleException("Could not create bundle object.", ex);
+ if (ex instanceof BundleException)
+ {
+ throw (BundleException) ex;
+ }
+ else
+ {
+ throw new BundleException("Could not create bundle object.", ex);
+ }
}
// If the bundle is new, then set its start level; existing
@@ -3090,7 +3097,9 @@
throw new BundleException(
"Unresolved constraint in bundle "
+ Util.getBundleIdFromModuleId(ex.getModule().getId())
- + ": " + ex.getRequirement());
+ + ": "
+ + ((ex.getRequirement() == null)
+ ? ex.getMessage() : ex.getRequirement().toString()));
}
else
{
@@ -3448,6 +3457,9 @@
m_configMutableMap.put(
FelixConstants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE,
"true");
+ m_configMutableMap.put(
+ FelixConstants.SUPPORTS_BOOTCLASSPATH_EXTENSION,
+ "false");
String s = null;
s = R4LibraryClause.normalizeOSName(System.getProperty("os.name"));
@@ -3687,10 +3699,28 @@
verifyExecutionEnvironment(bundle);
- Map resolvedModuleWireMap = m_resolver.resolve(m_resolverState, rootModule);
+ // Before trying to resolve, tell the resolver state to
+ // merge all fragments into host, which may result in the
+ // rootModule changing if the real root is a module.
+ IModule newRootModule;
+ try
+ {
+ newRootModule = m_resolverState.mergeFragments(rootModule);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ throw new ResolveException("Unable to merge fragments", rootModule, null);
+ }
- // Mark all modules as resolved.
- markResolvedModules(resolvedModuleWireMap);
+ if (!Util.isFragment(newRootModule))
+ {
+ // Resolve the module.
+ Map resolvedModuleWireMap = m_resolver.resolve(m_resolverState, newRootModule);
+
+ // Mark all modules as resolved.
+ markResolvedModules(resolvedModuleWireMap);
+ }
}
finally
{
@@ -3786,11 +3816,9 @@
Iterator iter = resolvedModuleWireMap.entrySet().iterator();
// Iterate over the map to mark the modules as resolved and
// update our resolver data structures.
- List fragmentList = new ArrayList();
List wireList = new ArrayList();
while (iter.hasNext())
{
- fragmentList.clear();
wireList.clear();
Map.Entry entry = (Map.Entry) iter.next();
@@ -3804,55 +3832,31 @@
{
for (int wireIdx = 0; wireIdx < wires.length; wireIdx++)
{
- if (wires[wireIdx] instanceof R4WireFragment)
- {
- fragmentList.add(wires[wireIdx].getExporter());
- }
- else
- {
-m_logger.log(Logger.LOG_DEBUG, "WIRE: " + wires[wireIdx]);
- wireList.add(wires[wireIdx]);
- }
+ wireList.add(wires[wireIdx]);
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "WIRE: " + wires[wireIdx]);
}
wires = (IWire[]) wireList.toArray(new IWire[wireList.size()]);
((ModuleImpl) module).setWires(wires);
}
+ // Resolve all attached fragments.
+ IModule[] fragments = ((ModuleImpl) module).getFragments();
+ for (int i = 0; (fragments != null) && (i < fragments.length); i++)
+ {
+ ((ModuleImpl) fragments[i]).setResolved();
+ // Update the state of the module's bundle to resolved as well.
+ markBundleResolved(fragments[i]);
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "FRAGMENT WIRE: " + fragments[i] + " -> hosted by -> " + module);
+ }
// Update the resolver state to show the module as resolved.
((ModuleImpl) module).setResolved();
m_resolverState.moduleResolved(module);
// Update the state of the module's bundle to resolved as well.
markBundleResolved(module);
-
- // Attach and mark all fragments as resolved.
- attachFragments(module, fragmentList);
- }
- }
- }
-
- private void attachFragments(IModule host, List fragmentList)
- {
- // Attach fragments to host module.
- if (fragmentList.size() > 0)
- {
- for (int i = 0; i < fragmentList.size(); i++)
- {
-m_logger.log(Logger.LOG_DEBUG, "(FRAGMENT) WIRE: " + host + " -> hosts -> " + fragmentList.get(i));
-
- // Update the resolver state to show the module as resolved.
- ((ModuleImpl) fragmentList.get(i)).setResolved();
- m_resolverState.moduleResolved((IModule) fragmentList.get(i));
- // Update the state of the module's bundle to resolved as well.
- markBundleResolved((IModule) fragmentList.get(i));
- }
- try
- {
- ((ModuleImpl) host).attachFragments(
- (IModule[]) fragmentList.toArray(new IModule[fragmentList.size()]));
- }
- catch (Exception ex)
- {
- m_logger.log(Logger.LOG_ERROR, "Unable to attach fragments", ex);
}
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
index 46b691e..ffcd219 100644
--- a/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
+++ b/framework/src/main/java/org/apache/felix/framework/FelixResolverState.java
@@ -42,6 +42,8 @@
private final Logger m_logger;
// List of all modules.
private final List m_moduleList = new ArrayList();
+ // Map of fragment symbolic names to array of modules sorted version.
+ private final Map m_fragmentMap = new HashMap();
// Maps a package name to an array of modules.
private final Map m_unresolvedPkgIndexMap = new HashMap();
// Maps a package name to an array of modules.
@@ -58,20 +60,210 @@
m_logger = logger;
}
+ public synchronized IModule mergeFragments(IModule rootModule) throws Exception
+ {
+// TODO: FRAGMENT - This should check to make sure that the host allows fragments.
+ IModule newRootModule = rootModule;
+ for (int hostIdx = 0; hostIdx < m_moduleList.size(); hostIdx++)
+ {
+ IModule host = (IModule) m_moduleList.get(hostIdx);
+ if (!host.isResolved() && !Util.isFragment(host))
+ {
+ ICapability[] caps = host.getCapabilities();
+ ICapability bundleCap = null;
+ for (int capIdx = 0; capIdx < caps.length; capIdx++)
+ {
+ if (caps[capIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
+ {
+ bundleCap = caps[capIdx];
+ break;
+ }
+ }
+
+ // Need to remove any previously attached, but not resolved fragments.
+ // TODO: FRAGMENT - Would be better to have the previous resolves
+ // not leave fragments attached.
+ ((ModuleImpl) host).attachFragments(null);
+
+ // Fragments are grouped by symbolic name and descending version.
+ // Attach the first matching fragment from each group if possible,
+ // since only one version of a given fragment may attach to a host.
+ List list = new ArrayList();
+ for (Iterator it = m_fragmentMap.entrySet().iterator(); it.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) it.next();
+ IModule[] fragments = (IModule[]) entry.getValue();
+ done: for (int fragIdx = 0; fragIdx < fragments.length; fragIdx++)
+ {
+ IRequirement[] reqs = fragments[fragIdx].getRequirements();
+ for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
+ {
+ if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE)
+ && reqs[reqIdx].isSatisfied(bundleCap)
+ && !((BundleImpl) fragments[fragIdx].getBundle()).isStale()
+ && !((BundleImpl) fragments[fragIdx].getBundle()).isRemovalPending())
+ {
+ // Fragments are attached in bundle ID order.
+ int index = -1;
+ for (int listIdx = 0;
+ (index < 0) && (listIdx < list.size());
+ listIdx++)
+ {
+ if (fragments[fragIdx].getBundle().getBundleId()
+ < ((IModule) list.get(listIdx)).getBundle().getBundleId())
+ {
+ index = listIdx;
+ }
+ }
+ list.add((index < 0) ? list.size() : index, fragments[fragIdx]);
+ break done;
+ }
+ }
+ }
+ }
+
+ if (list.size() > 0)
+ {
+ // Verify the fragments do not have conflicting imports.
+ // For now, just check for duplicate imports, but in the
+ // future we might want to make this more fine grained.
+ // First get the host's imported packages.
+ Map ipMerged = new HashMap();
+ Map rbMerged = new HashMap();
+ IRequirement[] reqs = host.getRequirements();
+ for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
+ {
+ if (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ ipMerged.put(((Requirement) reqs[reqIdx]).getTargetName(), host);
+ }
+ else if (reqs[reqIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ rbMerged.put(((Requirement) reqs[reqIdx]).getTargetName(), host);
+ }
+ }
+ // Loop through all fragments verifying they do no conflict,
+ // adding those packages that do not conflict and removing
+ // the fragment if it does conflict.
+ for (Iterator it = list.iterator(); it.hasNext(); )
+ {
+ IModule fragment = (IModule) it.next();
+ reqs = fragment.getRequirements();
+ List ipFragment = new ArrayList();
+ List rbFragment = new ArrayList();
+ boolean conflicting = false;
+ for (int reqIdx = 0;
+ !conflicting && (reqs != null) && (reqIdx < reqs.length);
+ reqIdx++)
+ {
+ if (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+ || reqs[reqIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ String targetName = ((Requirement) reqs[reqIdx]).getTargetName();
+ Map mergedReqMap = (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ ? ipMerged : rbMerged;
+ List fragmentReqList = (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ ? ipFragment : rbFragment;
+ if (mergedReqMap.get(targetName) == null)
+ {
+ fragmentReqList.add(targetName);
+ }
+ else
+ {
+ conflicting = true;
+ }
+ if (conflicting)
+ {
+ ipFragment.clear();
+ rbFragment.clear();
+ it.remove();
+ m_logger.log(
+ Logger.LOG_DEBUG,
+ "Excluding fragment " + fragment.getSymbolicName()
+ + " from " + host.getSymbolicName()
+ + " due to conflict with "
+ + (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+ ? "imported package " : "required bundle ")
+ + targetName + " from "
+ + ((IModule) mergedReqMap.get(targetName)).getSymbolicName());
+ }
+ }
+ }
+
+ // Merge non-conflicting requirements into overall set
+ // of requirements and continue checking for conflicts
+ // with the next fragment.
+ for (int pkgIdx = 0; pkgIdx < ipFragment.size(); pkgIdx++)
+ {
+ ipMerged.put(ipFragment.get(pkgIdx), fragment);
+ }
+ for (int pkgIdx = 0; pkgIdx < rbFragment.size(); pkgIdx++)
+ {
+ rbMerged.put(rbFragment.get(pkgIdx), fragment);
+ }
+ }
+
+ // Attach the fragments to the host.
+ IModule[] fragments = (IModule[]) list.toArray(new IModule[list.size()]);
+ ((ModuleImpl) host).attachFragments(fragments);
+
+ for (int fragIdx = 0; fragIdx < fragments.length; fragIdx++)
+ {
+ // Check to see if the root module is actually a fragment,
+ // if so then we want to return the host for resolving.
+ if (rootModule == fragments[fragIdx])
+ {
+ newRootModule = host;
+ }
+
+ // Add each fragment capabililty to the resolver state
+ // data structures.
+ ICapability[] fragCaps = fragments[fragIdx].getCapabilities();
+ for (int capIdx = 0; (fragCaps != null) && (capIdx < fragCaps.length); capIdx++)
+ {
+ if (fragCaps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ indexPackageCapability(
+ m_unresolvedPkgIndexMap, host, fragCaps[capIdx]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return newRootModule;
+ }
+
+ private void addFragment(IModule module)
+ {
+ indexFragment(m_fragmentMap, module);
+// System.out.println("+++ BEGIN FRAGMENT DUMP");
+// dumpModuleIndexMap(m_fragmentMap);
+// System.out.println("+++ END FRAGMENT DUMP");
+ }
+
public synchronized void addModule(IModule module)
{
- // When a module is added, create an aggregated list of unresolved
- // exports to simplify later processing when resolving bundles.
- m_moduleList.add(module);
-
- ICapability[] caps = module.getCapabilities();
-
- // Add exports to unresolved package map.
- for (int i = 0; (caps != null) && (i < caps.length); i++)
+ if (Util.isFragment(module))
{
- if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ addFragment(module);
+ }
+ else
+ {
+ // When a module is added, create an aggregated list of unresolved
+ // exports to simplify later processing when resolving bundles.
+ m_moduleList.add(module);
+
+ ICapability[] caps = module.getCapabilities();
+
+ // Add exports to unresolved package map.
+ for (int i = 0; (caps != null) && (i < caps.length); i++)
{
- indexPackageCapability(m_unresolvedPkgIndexMap, module, caps[i]);
+ if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ indexPackageCapability(m_unresolvedPkgIndexMap, module, caps[i]);
+ }
}
}
@@ -83,58 +275,77 @@
public synchronized void removeModule(IModule module)
{
- // When a module is removed from the system, we need remove
- // its exports from the "resolved" and "unresolved" package maps,
- // remove the module's dependencies on fragments and exporters,
- // and remove the module from the module data map.
+ // Depending on whether the module is a fragment or not,
+ // we need to do different things.
- m_moduleList.remove(module);
-
- // Remove exports from package maps.
- ICapability[] caps = module.getCapabilities();
- for (int i = 0; (caps != null) && (i < caps.length); i++)
+ // If module is a fragment, then remove from fragment map.
+ if (Util.isFragment(module))
{
- if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ IModule[] fragments = (IModule[]) m_fragmentMap.get(module.getSymbolicName());
+ fragments = removeModuleFromArray(fragments, module);
+ if (fragments.length == 0)
{
- // Get package name.
- String pkgName = (String)
- caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY);
- // Remove from "unresolved" package map.
- IModule[] modules = (IModule[]) m_unresolvedPkgIndexMap.get(pkgName);
- if (modules != null)
- {
- modules = removeModuleFromArray(modules, module);
- m_unresolvedPkgIndexMap.put(pkgName, modules);
- }
-
- // Remove from "resolved" package map.
- modules = (IModule[]) m_resolvedPkgIndexMap.get(pkgName);
- if (modules != null)
- {
- modules = removeModuleFromArray(modules, module);
- m_resolvedPkgIndexMap.put(pkgName, modules);
- }
+ m_fragmentMap.remove(module.getSymbolicName());
+ }
+ else
+ {
+ m_fragmentMap.put(module.getSymbolicName(), fragments);
}
}
+ // If it is not a fragment, then we need remove its exports
+ // from the "resolved" and "unresolved" package maps, remove
+ // the module's dependencies on fragments and exporters,
+ // and remove the module from the module list.
+ else
+ {
+ m_moduleList.remove(module);
- // Set fragments to null, which will remove the module from all
- // of its dependent fragment modules.
- try
- {
- ((ModuleImpl) module).attachFragments(null);
+ // Remove exports from package maps.
+ ICapability[] caps = module.getCapabilities();
+ for (int i = 0; (caps != null) && (i < caps.length); i++)
+ {
+ if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ // Get package name.
+ String pkgName = (String)
+ caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY);
+ // Remove from "unresolved" package map.
+ IModule[] modules = (IModule[]) m_unresolvedPkgIndexMap.get(pkgName);
+ if (modules != null)
+ {
+ modules = removeModuleFromArray(modules, module);
+ m_unresolvedPkgIndexMap.put(pkgName, modules);
+ }
+
+ // Remove from "resolved" package map.
+ modules = (IModule[]) m_resolvedPkgIndexMap.get(pkgName);
+ if (modules != null)
+ {
+ modules = removeModuleFromArray(modules, module);
+ m_resolvedPkgIndexMap.put(pkgName, modules);
+ }
+ }
+ }
+
+ // Remove the module from the "resolved" map.
+ m_resolvedCapMap.remove(module);
+ // Set fragments to null, which will remove the module from all
+ // of its dependent fragment modules.
+ try
+ {
+ ((ModuleImpl) module).attachFragments(null);
+ }
+ catch (Exception ex)
+ {
+ m_logger.log(Logger.LOG_ERROR, "Error detaching fragments.", ex);
+ }
+ // Set wires to null, which will remove the module from all
+ // of its dependent modules.
+ ((ModuleImpl) module).setWires(null);
}
- catch (Exception ex)
- {
- m_logger.log(Logger.LOG_ERROR, "Error detaching fragments.", ex);
- }
- // Set wires to null, which will remove the module from all
- // of its dependent modules.
- ((ModuleImpl) module).setWires(null);
+
// Close the module's content.
((ModuleImpl) module).close();
-
- // Remove the module from the "resolved" map.
- m_resolvedCapMap.remove(module);
}
/**
@@ -168,6 +379,26 @@
}
}
+ private void dumpModuleIndexMap(Map moduleIndexMap)
+ {
+ for (Iterator i = moduleIndexMap.entrySet().iterator(); i.hasNext(); )
+ {
+ Map.Entry entry = (Map.Entry) i.next();
+ IModule[] modules = (IModule[]) entry.getValue();
+ if ((modules != null) && (modules.length > 0))
+ {
+ if (!((modules.length == 1) && modules[0].getId().equals("0")))
+ {
+ System.out.println(" " + entry.getKey());
+ for (int j = 0; j < modules.length; j++)
+ {
+ System.out.println(" " + modules[j]);
+ }
+ }
+ }
+ }
+ }
+
private void dumpPackageIndexMap(Map pkgIndexMap)
{
for (Iterator i = pkgIndexMap.entrySet().iterator(); i.hasNext(); )
@@ -303,93 +534,15 @@
//dumpPackageIndexMap(m_resolvedPkgIndexMap);
}
- // TODO: FRAGMENT - Not very efficient.
- public synchronized List getPotentialHosts(IModule fragment)
- {
- List hostList = new ArrayList();
-
- IRequirement[] reqs = fragment.getRequirements();
- IRequirement hostReq = null;
- for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
- {
- if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
- {
- hostReq = reqs[reqIdx];
- break;
- }
- }
-
- IModule[] modules = getModules();
- for (int modIdx = 0; (hostReq != null) && (modIdx < modules.length); modIdx++)
- {
- if (!fragment.equals(modules[modIdx]) && !modules[modIdx].isResolved())
- {
- ICapability[] caps = modules[modIdx].getCapabilities();
- for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
- {
- if (caps[capIdx].getNamespace().equals(ICapability.HOST_NAMESPACE)
- && hostReq.isSatisfied(caps[capIdx])
- && !((BundleImpl) modules[modIdx].getBundle()).isStale())
- {
- hostList.add(modules[modIdx]);
- break;
- }
- }
- }
- }
-
- return hostList;
- }
-
-// TODO: FRAGMENT - Not very efficient.
- public synchronized Map getPotentialFragments(IModule host)
- {
-// TODO: FRAGMENT - This should check to make sure that the host allows fragments.
- Map fragmentMap = new HashMap();
-
- ICapability[] caps = host.getCapabilities();
- ICapability bundleCap = null;
- for (int capIdx = 0; capIdx < caps.length; capIdx++)
- {
- if (caps[capIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
- {
- bundleCap = caps[capIdx];
- break;
- }
- }
-
- IModule[] modules = getModules();
- for (int modIdx = 0; (bundleCap != null) && (modIdx < modules.length); modIdx++)
- {
- if (!host.equals(modules[modIdx]))
- {
- IRequirement[] reqs = modules[modIdx].getRequirements();
- for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
- {
- if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE)
- && reqs[reqIdx].isSatisfied(bundleCap)
- && !((BundleImpl) modules[modIdx].getBundle()).isStale()
- && !((BundleImpl) modules[modIdx].getBundle()).isRemovalPending())
- {
- indexFragment(fragmentMap, modules[modIdx]);
- break;
- }
- }
- }
- }
-
- return fragmentMap;
- }
-
public synchronized PackageSource[] getResolvedCandidates(IRequirement req)
{
// Synchronized on the module manager to make sure that no
// modules are added, removed, or resolved.
PackageSource[] candidates = m_emptySources;
if (req.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
- && (((Requirement) req).getPackageName() != null))
+ && (((Requirement) req).getTargetName() != null))
{
- String pkgName = ((Requirement) req).getPackageName();
+ String pkgName = ((Requirement) req).getTargetName();
IModule[] modules = (IModule[]) m_resolvedPkgIndexMap.get(pkgName);
for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++)
@@ -464,9 +617,9 @@
// Get all modules.
IModule[] modules = null;
if (req.getNamespace().equals(ICapability.PACKAGE_NAMESPACE) &&
- (((Requirement) req).getPackageName() != null))
+ (((Requirement) req).getTargetName() != null))
{
- modules = (IModule[]) m_unresolvedPkgIndexMap.get(((Requirement) req).getPackageName());
+ modules = (IModule[]) m_unresolvedPkgIndexMap.get(((Requirement) req).getTargetName());
}
else
{
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
index 2173dfc..5dee8b9 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/ModuleImpl.java
@@ -30,6 +30,7 @@
import java.security.ProtectionDomain;
import java.security.SecureClassLoader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
@@ -224,19 +225,71 @@
return m_version;
}
- public ICapability[] getCapabilities()
+ public synchronized ICapability[] getCapabilities()
{
- return m_capabilities;
+ List capList = (m_capabilities == null)
+ ? new ArrayList() : new ArrayList(Arrays.asList(m_capabilities));
+ for (int fragIdx = 0;
+ (m_fragments != null) && (fragIdx < m_fragments.length);
+ fragIdx++)
+ {
+ ICapability[] caps = m_fragments[fragIdx].getCapabilities();
+ for (int capIdx = 0;
+ (caps != null) && (capIdx < caps.length);
+ capIdx++)
+ {
+ if (caps[capIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ capList.add(caps[capIdx]);
+ }
+ }
+ }
+ return (ICapability[]) capList.toArray(new ICapability[capList.size()]);
}
- public IRequirement[] getRequirements()
+ public synchronized IRequirement[] getRequirements()
{
- return m_requirements;
+ List reqList = (m_requirements == null)
+ ? new ArrayList() : new ArrayList(Arrays.asList(m_requirements));
+ for (int fragIdx = 0;
+ (m_fragments != null) && (fragIdx < m_fragments.length);
+ fragIdx++)
+ {
+ IRequirement[] reqs = m_fragments[fragIdx].getRequirements();
+ for (int reqIdx = 0;
+ (reqs != null) && (reqIdx < reqs.length);
+ reqIdx++)
+ {
+ if (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)
+ || reqs[reqIdx].getNamespace().equals(ICapability.MODULE_NAMESPACE))
+ {
+ reqList.add(reqs[reqIdx]);
+ }
+ }
+ }
+ return (IRequirement[]) reqList.toArray(new IRequirement[reqList.size()]);
}
- public IRequirement[] getDynamicRequirements()
+ public synchronized IRequirement[] getDynamicRequirements()
{
- return m_dynamicRequirements;
+ List reqList = (m_dynamicRequirements == null)
+ ? new ArrayList() : new ArrayList(Arrays.asList(m_dynamicRequirements));
+ for (int fragIdx = 0;
+ (m_fragments != null) && (fragIdx < m_fragments.length);
+ fragIdx++)
+ {
+ IRequirement[] reqs = m_fragments[fragIdx].getDynamicRequirements();
+ for (int reqIdx = 0;
+ (reqs != null) && (reqIdx < reqs.length);
+ reqIdx++)
+ {
+ if (reqs[reqIdx].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
+ {
+ reqList.add(reqs[reqIdx]);
+ }
+ }
+ }
+ return (IRequirement[]) reqList.toArray(new IRequirement[reqList.size()]);
}
public R4Library[] getNativeLibraries()
@@ -334,15 +387,16 @@
private IContent[] initializeContentPath() throws Exception
{
List contentList = new ArrayList();
- calculateContentPath(m_content, contentList, true);
+ calculateContentPath(this, m_content, contentList, true);
for (int i = 0; (m_fragmentContents != null) && (i < m_fragmentContents.length); i++)
{
- calculateContentPath(m_fragmentContents[i], contentList, false);
+ calculateContentPath(m_fragments[i], m_fragmentContents[i], contentList, false);
}
return (IContent[]) contentList.toArray(new IContent[contentList.size()]);
}
- private List calculateContentPath(IContent content, List contentList, boolean searchFragments)
+ private List calculateContentPath(
+ IModule module, IContent content, List contentList, boolean searchFragments)
throws Exception
{
// Creating the content path entails examining the bundle's
@@ -354,7 +408,7 @@
List localContentList = new ArrayList();
// Find class path meta-data.
- String classPath = (String) m_headerMap.get(FelixConstants.BUNDLE_CLASSPATH);
+ String classPath = (String) module.getHeaders().get(FelixConstants.BUNDLE_CLASSPATH);
// Parse the class path into strings.
String[] classPathStrings = ManifestParser.parseDelimitedString(
classPath, FelixConstants.CLASS_PATH_SEPARATOR);
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireFragment.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireFragment.java
deleted file mode 100644
index 929e8af..0000000
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4WireFragment.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.apache.felix.framework.searchpolicy;
-
-import java.net.URL;
-import java.util.Enumeration;
-
-import org.apache.felix.framework.util.Util;
-import org.apache.felix.framework.util.manifestparser.Capability;
-import org.apache.felix.moduleloader.*;
-
-// TODO: RESOLVER - This is a hack and doesn't really fit with abstraction.
-public class R4WireFragment implements IWire
-{
- private final IModule m_importer;
- private final IRequirement m_requirement;
- private final IModule m_exporter;
- private final ICapability m_capability;
-
- public R4WireFragment(IModule host, IModule fragment)
- {
- m_importer = host;
- m_requirement = null;
- m_exporter = fragment;
- m_capability = null;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getImporter()
- */
- public IModule getImporter()
- {
- return m_importer;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getRequirement()
- */
- public IRequirement getRequirement()
- {
- return m_requirement;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getExporter()
- */
- public IModule getExporter()
- {
- return m_exporter;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getCapability()
- */
- public ICapability getCapability()
- {
- return m_capability;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getClass(java.lang.String)
- */
- public boolean hasPackage(String pkgName)
- {
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getClass(java.lang.String)
- */
- public Class getClass(String name) throws ClassNotFoundException
- {
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getResource(java.lang.String)
- */
- public URL getResource(String name) throws ResourceNotFoundException
- {
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.apache.felix.framework.searchpolicy.IWire#getResources(java.lang.String)
- */
- public Enumeration getResources(String name) throws ResourceNotFoundException
- {
- return null;
- }
-
- public String toString()
- {
- return m_importer + " -> hosts -> " + m_exporter;
- }
-}
\ No newline at end of file
diff --git a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
index edd1464..d3a8bb7 100644
--- a/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
+++ b/framework/src/main/java/org/apache/felix/framework/searchpolicy/Resolver.java
@@ -216,7 +216,7 @@
// First check to see if the dynamic requirement matches the
// package name; this means we have to do wildcard matching.
- String dynPkgName = ((Requirement) dynReq).getPackageName();
+ String dynPkgName = ((Requirement) dynReq).getTargetName();
boolean wildcard = (dynPkgName.lastIndexOf(".*") >= 0);
// Remove the "*", but keep the "." if wildcarded.
dynPkgName = (wildcard)
@@ -354,194 +354,82 @@
// detect cycles.
candidatesMap.put(targetModule, candSetList);
- // Loop through potential fragments and add each set to the
- // candidate set; if the targetModule is a fragment then there
- // will be no potential fragments here.
- Map fragmentMap = state.getPotentialFragments(targetModule);
- for (Iterator it = fragmentMap.entrySet().iterator(); it.hasNext(); )
- {
- Map.Entry entry = (Map.Entry) it.next();
- IModule[] fragments = (IModule[]) entry.getValue();
-
- // If we have fragment candidates, then we need to recursively populate
- // the resolver map with each of them.
- if (fragments.length > 0)
- {
- for (int fragIdx = 0; fragIdx < fragments.length; fragIdx++)
- {
- try
- {
- // We still need to populate the candidates for the
- // fragment even if it is resolved, because fragments
- // can be attached to multiple hosts and each host
- // may end up with different wires for the fragments
- // dependencies.
- populateCandidatesMap(state, candidatesMap, fragments[fragIdx]);
- }
- catch (ResolveException ex)
- {
- // If we received a resolve exception, then the
- // current fragment is not resolvable for some
- // reason and should be removed from the list of
- // fragments. For now, just null it.
- fragments[fragIdx] = null;
- }
- }
-
- // Remove any nulled fragments to create the final list
- // of potential fragment candidates.
- fragments = shrinkModuleArray(fragments);
- }
-
- // All fragments, by definition, are optional so we if none of the
- // candidates could be resolved, then just ignore them; otherwise,
- // add the resolvable fragments to the host's candidate set.
- if (fragments.length > 0)
- {
- candSetList.add(
- new CandidateSet(CandidateSet.FRAGMENT, targetModule, null, fragments));
- }
- }
-
// Loop through each requirement and calculate its resolving
// set of candidates.
IRequirement[] reqs = targetModule.getRequirements();
for (int reqIdx = 0; (reqs != null) && (reqIdx < reqs.length); reqIdx++)
{
- if (reqs[reqIdx].getNamespace().equals(ICapability.HOST_NAMESPACE))
+ // Get the candidates from the "resolved" and "unresolved"
+ // package maps. The "resolved" candidates have higher priority
+ // than "unresolved" ones, so put the "resolved" candidates
+ // at the front of the list of candidates.
+ PackageSource[] resolved = state.getResolvedCandidates(reqs[reqIdx]);
+ PackageSource[] unresolved = state.getUnresolvedCandidates(reqs[reqIdx]);
+ PackageSource[] candidates = new PackageSource[resolved.length + unresolved.length];
+ System.arraycopy(resolved, 0, candidates, 0, resolved.length);
+ System.arraycopy(unresolved, 0, candidates, resolved.length, unresolved.length);
+
+ // If we have candidates, then we need to recursively populate
+ // the resolver map with each of them.
+ ResolveException rethrow = null;
+ if (candidates.length > 0)
{
- List hostList = state.getPotentialHosts(targetModule);
- IModule[] hosts = (IModule[]) hostList.toArray(new IModule[hostList.size()]);
- // If we have host candidates, then we need to recursively populate
- // the resolver map with each of them.
- ResolveException rethrow = null;
- if (hosts.length > 0)
+ for (int candIdx = 0; candIdx < candidates.length; candIdx++)
{
- for (int hostIdx = 0; hostIdx < hosts.length; hostIdx++)
+ try
{
- try
+ // Only populate the resolver map with modules that
+ // are not already resolved.
+ if (!candidates[candIdx].m_module.isResolved())
{
- // Only populate the resolver map with hosts that
- // are not already resolved.
- if (!hosts[hostIdx].isResolved())
- {
- populateCandidatesMap(state, candidatesMap, hosts[hostIdx]);
- }
- }
- catch (ResolveException ex)
- {
- // If we received a resolve exception, then the
- // current host is not resolvable for some
- // reason and should be removed from the list of
- // hosts. For now, just null it.
- hosts[hostIdx] = null;
- rethrow = ex;
+ populateCandidatesMap(state, candidatesMap, candidates[candIdx].m_module);
}
}
-
- // Remove any nulled hosts to create the final list
- // of potential host candidates.
- hosts = shrinkModuleArray(hosts);
- }
-
- // If no host candidates exist at this point, then throw a
- // resolve exception since all fragments must have a host.
- if (hosts.length == 0)
- {
- // If we have received an exception while trying to populate
- // the candidates map, rethrow that exception since it might
- // be useful. NOTE: This is not necessarily the "only"
- // correct exception, since it is possible that multiple
- // candidates were not resolvable, but it is better than
- // nothing.
- if (rethrow != null)
+ catch (ResolveException ex)
{
- throw rethrow;
- }
- else
- {
- throw new ResolveException(
- "Unable to find host for fragment.",
- targetModule, reqs[reqIdx]);
+ // If we received a resolve exception, then the
+ // current candidate is not resolvable for some
+ // reason and should be removed from the list of
+ // candidates. For now, just null it.
+ candidates[candIdx] = null;
+ rethrow = ex;
}
}
- candSetList.add(
- new CandidateSet(CandidateSet.HOST, targetModule, reqs[reqIdx], hosts));
+
+ // Remove any nulled candidates to create the final list
+ // of available candidates.
+ candidates = shrinkCandidateArray(candidates);
}
- else
+
+ // If no candidates exist at this point, then throw a
+ // resolve exception unless the import is optional.
+ if ((candidates.length == 0) && !reqs[reqIdx].isOptional())
{
- // Get the candidates from the "resolved" and "unresolved"
- // package maps. The "resolved" candidates have higher priority
- // than "unresolved" ones, so put the "resolved" candidates
- // at the front of the list of candidates.
- PackageSource[] resolved = state.getResolvedCandidates(reqs[reqIdx]);
- PackageSource[] unresolved = state.getUnresolvedCandidates(reqs[reqIdx]);
- PackageSource[] candidates = new PackageSource[resolved.length + unresolved.length];
- System.arraycopy(resolved, 0, candidates, 0, resolved.length);
- System.arraycopy(unresolved, 0, candidates, resolved.length, unresolved.length);
+ // Since the target module cannot resolve, remove its
+ // candidates set list from the candidates map, since
+ // it is invalid.
+ candidatesMap.remove(targetModule);
- // If we have candidates, then we need to recursively populate
- // the resolver map with each of them.
- ResolveException rethrow = null;
- if (candidates.length > 0)
+ // If we have received an exception while trying to populate
+ // the candidates map, rethrow that exception since it might
+ // be useful. NOTE: This is not necessarily the "only"
+ // correct exception, since it is possible that multiple
+ // candidates were not resolvable, but it is better than
+ // nothing.
+ if (rethrow != null)
{
- for (int candIdx = 0; candIdx < candidates.length; candIdx++)
- {
- try
- {
- // Only populate the resolver map with modules that
- // are not already resolved.
- if (!candidates[candIdx].m_module.isResolved())
- {
- populateCandidatesMap(state, candidatesMap, candidates[candIdx].m_module);
- }
- }
- catch (ResolveException ex)
- {
- // If we received a resolve exception, then the
- // current candidate is not resolvable for some
- // reason and should be removed from the list of
- // candidates. For now, just null it.
- candidates[candIdx] = null;
- rethrow = ex;
- }
- }
-
- // Remove any nulled candidates to create the final list
- // of available candidates.
- candidates = shrinkCandidateArray(candidates);
+ throw rethrow;
}
-
- // If no candidates exist at this point, then throw a
- // resolve exception unless the import is optional.
- if ((candidates.length == 0) && !reqs[reqIdx].isOptional())
+ else
{
- // Since the target module cannot resolve, remove its
- // candidates set list from the candidates map, since
- // it is invalid.
- candidatesMap.remove(targetModule);
-
- // If we have received an exception while trying to populate
- // the candidates map, rethrow that exception since it might
- // be useful. NOTE: This is not necessarily the "only"
- // correct exception, since it is possible that multiple
- // candidates were not resolvable, but it is better than
- // nothing.
- if (rethrow != null)
- {
- throw rethrow;
- }
- else
- {
- throw new ResolveException(
- "Unable to resolve.", targetModule, reqs[reqIdx]);
- }
+ throw new ResolveException(
+ "Unable to resolve.", targetModule, reqs[reqIdx]);
}
- else if (candidates.length > 0)
- {
- candSetList.add(
- new CandidateSet(CandidateSet.NORMAL, targetModule, reqs[reqIdx], candidates));
- }
+ }
+ else if (candidates.length > 0)
+ {
+ candSetList.add(
+ new CandidateSet(CandidateSet.NORMAL, targetModule, reqs[reqIdx], candidates));
}
}
}
@@ -1121,18 +1009,6 @@
for (int candSetIdx = 0; (candSetList != null) && (candSetIdx < candSetList.size()); candSetIdx++)
{
CandidateSet cs = (CandidateSet) candSetList.get(candSetIdx);
-// TODO: FRAGMENT - Eventually fragments will import, so the imports of a fragment
-// will need to be added to the imports of the host.
- if (cs.m_type == CandidateSet.FRAGMENT)
- {
- continue;
- }
- else if (cs.m_type == CandidateSet.HOST)
- {
- // We can ignore the host candidates, since they will be
- // taken care of when resolving the host module.
- continue;
- }
PackageSource ps = cs.m_candidates[cs.m_idx];
if (ps.m_capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
@@ -1217,18 +1093,6 @@
for (int candSetIdx = 0; (candSetList != null) && (candSetIdx < candSetList.size()); candSetIdx++)
{
CandidateSet cs = (CandidateSet) candSetList.get(candSetIdx);
-// TODO: FRAGMENT - Eventually fragments will require bundles, so the required
-// packages of the fragment will need to be added to the host.
- if (cs.m_type == CandidateSet.FRAGMENT)
- {
- continue;
- }
- else if (cs.m_type == CandidateSet.HOST)
- {
- // We can ignore the host candidates, since they will be
- // taken care of when resolving the host module.
- continue;
- }
PackageSource ps = cs.m_candidates[cs.m_idx];
// If the capabaility is a module dependency, then flatten it to packages.
@@ -1345,18 +1209,6 @@
for (int candSetIdx = 0; candSetIdx < candSetList.size(); candSetIdx++)
{
CandidateSet cs = (CandidateSet) candSetList.get(candSetIdx);
-// TODO: FRAGMENT - Eventually fragments will export, so the exports of the
-// fragment will need to be added to the host.
- if (cs.m_type == CandidateSet.FRAGMENT)
- {
- continue;
- }
- else if (cs.m_type == CandidateSet.HOST)
- {
- // We can ignore the host candidates, since they will be
- // taken care of when resolving the host module.
- continue;
- }
PackageSource ps = cs.m_candidates[cs.m_idx];
// If the candidate is resolving a module dependency, then
@@ -1620,59 +1472,6 @@
// Get the candidate set list for the importer.
List candSetList = (List) candidatesMap.get(importer);
- // Check if the importer is a fragment, if so we actually want
- // to get the host and add all fragments candidates to it.
- if (Util.isFragment(importer))
- {
- // Get host candidate for the fragment.
- IModule host = null;
- for (int csIdx = 0; (host == null) && (csIdx < candSetList.size()); csIdx++)
- {
- CandidateSet cs = (CandidateSet) candSetList.get(csIdx);
- if (cs.m_type == CandidateSet.HOST)
- {
- host = cs.m_modules[cs.m_idx];
- }
- }
- // Instead of creating wires for the fragment, we will create them
- // for the host.
- importer = host;
-
- // Make sure we haven't already seen the host to avoid a cycle.
- if (wireMap.get(importer) != null)
- {
- return wireMap;
- }
-
- // Now add the fragments candidates to the host.
- candSetList = (List) candidatesMap.get(host);
- for (int csIdx = 0; (host == null) && (csIdx < candSetList.size()); csIdx++)
- {
- CandidateSet cs = (CandidateSet) candSetList.get(csIdx);
- if (cs.m_type == CandidateSet.FRAGMENT)
- {
- // Add the candidate fragment module to the cycle map
- // with no wires, since only its host will have wires.
- wireMap.put(cs.m_modules[cs.m_idx], new IWire[0]);
-
- // Get the candidate fragment and loop through its candidates
- // for resolving its dependencies.
- List fragmentCandSetList = (List) candidatesMap.get(cs.m_modules[cs.m_idx]);
- for (int csFragIdx = 0; csFragIdx < fragmentCandSetList.size(); csFragIdx++)
- {
- // Add all non-HOST candidates to the host candidate set,
- // since the resulting wires will be for the host not
- // the fragment.
- CandidateSet csFrag = (CandidateSet) fragmentCandSetList.get(csFragIdx);
- if (csFrag.m_type != CandidateSet.HOST)
- {
- candSetList.add(csFrag);
- }
- }
- }
- }
- }
-
List moduleWires = new ArrayList();
List packageWires = new ArrayList();
@@ -1687,42 +1486,33 @@
// Get the current candidate set.
CandidateSet cs = (CandidateSet) candSetList.get(candSetIdx);
- // Create a wire for the current candidate based on the type
- // of requirement it resolves.
- if (cs.m_type == CandidateSet.FRAGMENT)
+ // Create a module wire for module dependencies.
+ if (cs.m_requirement.getNamespace().equals(ICapability.MODULE_NAMESPACE))
{
- moduleWires.add(new R4WireFragment(importer, cs.m_modules[cs.m_idx]));
+ moduleWires.add(new R4WireModule(
+ importer,
+ cs.m_requirement,
+ cs.m_candidates[cs.m_idx].m_module,
+ cs.m_candidates[cs.m_idx].m_capability,
+ calculateCandidateRequiredPackages(importer, cs.m_candidates[cs.m_idx], candidatesMap)));
}
- else
+ // Create a package wire for package dependencies.
+ // Filter out the case where a module imports from
+ // itself, since the module should simply load from
+ // its internal class path in this case.
+ else if (importer != cs.m_candidates[cs.m_idx].m_module)
{
- // Create a module wire for module dependencies.
- if (cs.m_requirement.getNamespace().equals(ICapability.MODULE_NAMESPACE))
- {
- moduleWires.add(new R4WireModule(
- importer,
- cs.m_requirement,
- cs.m_candidates[cs.m_idx].m_module,
- cs.m_candidates[cs.m_idx].m_capability,
- calculateCandidateRequiredPackages(importer, cs.m_candidates[cs.m_idx], candidatesMap)));
- }
- // Create a package wire for package dependencies.
- // Filter out the case where a module imports from
- // itself, since the module should simply load from
- // its internal class path in this case.
- else if (importer != cs.m_candidates[cs.m_idx].m_module)
- {
- // Add wire for imported package.
- packageWires.add(new R4Wire(
- importer,
- cs.m_requirement,
- cs.m_candidates[cs.m_idx].m_module,
- cs.m_candidates[cs.m_idx].m_capability));
- }
+ // Add wire for imported package.
+ packageWires.add(new R4Wire(
+ importer,
+ cs.m_requirement,
+ cs.m_candidates[cs.m_idx].m_module,
+ cs.m_candidates[cs.m_idx].m_capability));
+ }
- // Create any necessary wires for the selected candidate module.
- wireMap = populateWireMap(
- state, candidatesMap, cs.m_candidates[cs.m_idx].m_module, wireMap);
- }
+ // Create any necessary wires for the selected candidate module.
+ wireMap = populateWireMap(
+ state, candidatesMap, cs.m_candidates[cs.m_idx].m_module, wireMap);
}
packageWires.addAll(moduleWires);
@@ -1798,8 +1588,6 @@
public static interface ResolverState
{
IModule[] getModules();
- Map getPotentialFragments(IModule module);
- List getPotentialHosts(IModule module);
PackageSource[] getResolvedCandidates(IRequirement req);
PackageSource[] getUnresolvedCandidates(IRequirement req);
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
index d8e8e38..b7a336e 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
@@ -183,7 +183,7 @@
for (int reqIdx = 0; reqIdx < importReqs.length; reqIdx++)
{
// Verify that the named package has not already been declared.
- String pkgName = ((Requirement) importReqs[reqIdx]).getPackageName();
+ String pkgName = ((Requirement) importReqs[reqIdx]).getTargetName();
if (dupeMap.get(pkgName) == null)
{
@@ -221,7 +221,7 @@
for (int reqIdx = 0; reqIdx < m_dynamicRequirements.length; reqIdx++)
{
// Verify that java.* packages are not imported.
- String pkgName = ((Requirement) m_dynamicRequirements[reqIdx]).getPackageName();
+ String pkgName = ((Requirement) m_dynamicRequirements[reqIdx]).getTargetName();
if (pkgName.startsWith("java."))
{
throw new BundleException(
@@ -275,21 +275,19 @@
String fragmentHost = (String) headerMap.get(Constants.FRAGMENT_HOST);
if ((fragmentHost != null) && (parseExtensionBundleHeader(fragmentHost) == null))
{
- if ((headerMap.get(Constants.IMPORT_PACKAGE) != null)
- || (headerMap.get(Constants.EXPORT_PACKAGE) != null)
- || (headerMap.get(Constants.BUNDLE_NATIVECODE) != null))
+ if (headerMap.get(Constants.BUNDLE_NATIVECODE) != null)
{
String s = (String) m_configMap.get(FelixConstants.FRAGMENT_VALIDATION_PROP);
s = (s == null) ? FelixConstants.FRAGMENT_VALIDATION_EXCEPTION_VALUE : s;
if (s.equalsIgnoreCase(FelixConstants.FRAGMENT_VALIDATION_WARNING_VALUE))
{
m_logger.log(Logger.LOG_WARNING,
- "Fragments with exports, imports, or native code are not currently supported.");
+ "Fragments with native code are not currently supported.");
}
else
{
throw new BundleException(
- "Fragments with exports, imports, or native code are not currently supported.");
+ "Fragments native code are not currently supported.");
}
}
}
@@ -671,7 +669,7 @@
if (m_requirements[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE))
{
map.put(
- ((Requirement) m_requirements[i]).getPackageName(),
+ ((Requirement) m_requirements[i]).getTargetName(),
m_requirements[i]);
}
}
@@ -714,7 +712,7 @@
{
usesValue = usesValue
+ ((usesValue.length() > 0) ? "," : "")
- + ((Requirement) m_requirements[i]).getPackageName();
+ + ((Requirement) m_requirements[i]).getTargetName();
}
}
R4Directive uses = new R4Directive(
@@ -1119,6 +1117,7 @@
}
public static R4Directive parseExtensionBundleHeader(String header)
+ throws BundleException
{
Object[][][] clauses = parseStandardHeader(header);
@@ -1126,15 +1125,25 @@
if (clauses.length == 1)
{
- if (FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]) ||
- Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]))
+ // See if there is the "extension" directive.
+ for (int i = 0;
+ (result == null) && (i < clauses[0][CLAUSE_DIRECTIVES_INDEX].length);
+ i++)
{
- if (clauses[0][CLAUSE_DIRECTIVES_INDEX].length == 1)
+ if (Constants.EXTENSION_DIRECTIVE.equals(((R4Directive)
+ clauses[0][CLAUSE_DIRECTIVES_INDEX][i]).getName()))
{
- if (Constants.EXTENSION_DIRECTIVE.equals(((R4Directive)
- clauses[0][CLAUSE_DIRECTIVES_INDEX][0]).getName()))
+ // If the extension directive is specified, make sure
+ // the target is the system bundle.
+ if (FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]) ||
+ Constants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(clauses[0][CLAUSE_PATHS_INDEX][0]))
{
- result = (R4Directive) clauses[0][CLAUSE_DIRECTIVES_INDEX][0];
+ result = (R4Directive) clauses[0][CLAUSE_DIRECTIVES_INDEX][i];
+ }
+ else
+ {
+ throw new BundleException(
+ "Only the system bundle can have extension bundles.");
}
}
}
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
index 61d24a4..c8b97e6 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/Requirement.java
@@ -28,18 +28,23 @@
public class Requirement implements IRequirement
{
private final String m_namespace;
- private R4Directive[] m_directives;
- private R4Attribute[] m_attributes;
- private boolean m_isOptional = false;
+ private final R4Directive[] m_directives;
+ private final R4Attribute[] m_attributes;
+ private final boolean m_isOptional;
- private String m_pkgName;
- private VersionRange m_pkgVersionRange;
- private Filter m_filter;
+ private final String m_targetName;
+ private final VersionRange m_targetVersionRange;
+ private volatile Filter m_filter;
public Requirement(String namespace, String filterStr) throws InvalidSyntaxException
{
m_namespace = namespace;
m_filter = new FilterImpl(filterStr);
+ m_directives = null;
+ m_attributes = null;
+ m_isOptional = false;
+ m_targetName = null;
+ m_targetVersionRange = null;
}
public Requirement(String namespace, R4Directive[] directives, R4Attribute[] attributes)
@@ -47,33 +52,59 @@
m_namespace = namespace;
m_directives = directives;
m_attributes = attributes;
+ m_filter = null;
// Find all import directives: resolution.
+ boolean optional = false;
for (int i = 0; (m_directives != null) && (i < m_directives.length); i++)
{
if (m_directives[i].getName().equals(Constants.RESOLUTION_DIRECTIVE))
{
- m_isOptional = m_directives[i].getValue().equals(Constants.RESOLUTION_OPTIONAL);
+ optional = m_directives[i].getValue().equals(Constants.RESOLUTION_OPTIONAL);
}
}
+ m_isOptional = optional;
+ String targetName = null;
+ VersionRange targetVersionRange = VersionRange.infiniteRange;
for (int i = 0; i < m_attributes.length; i++)
{
- if (m_attributes[i].getName().equals(ICapability.PACKAGE_PROPERTY))
+ if (m_namespace.equals(ICapability.MODULE_NAMESPACE))
{
- m_pkgName = (String) m_attributes[i].getValue();
+ if (m_attributes[i].getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
+ {
+ targetName = (String) m_attributes[i].getValue();
+ }
+ else if (m_attributes[i].getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+ {
+ targetVersionRange = (VersionRange) m_attributes[i].getValue();
+ }
}
- else if (m_namespace.equals(ICapability.PACKAGE_NAMESPACE) &&
- m_attributes[i].getName().equals(ICapability.VERSION_PROPERTY))
+ else if (m_namespace.equals(ICapability.PACKAGE_NAMESPACE))
{
- m_pkgVersionRange = (VersionRange) m_attributes[i].getValue();
+ if (m_attributes[i].getName().equals(ICapability.PACKAGE_PROPERTY))
+ {
+ targetName = (String) m_attributes[i].getValue();
+ }
+ else if (m_attributes[i].getName().equals(ICapability.VERSION_PROPERTY))
+ {
+ targetVersionRange = (VersionRange) m_attributes[i].getValue();
+ }
+ }
+ else if (m_namespace.equals(ICapability.HOST_NAMESPACE))
+ {
+ if (m_attributes[i].getName().equals(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE))
+ {
+ targetName = (String) m_attributes[i].getValue();
+ }
+ else if (m_attributes[i].getName().equals(Constants.BUNDLE_VERSION_ATTRIBUTE))
+ {
+ targetVersionRange = (VersionRange) m_attributes[i].getValue();
+ }
}
}
-
- if (m_pkgVersionRange == null)
- {
- m_pkgVersionRange = VersionRange.infiniteRange;
- }
+ m_targetName = targetName;
+ m_targetVersionRange = targetVersionRange;
}
public String getNamespace()
@@ -93,14 +124,14 @@
// TODO: RB - We need to verify that the resolver code does not
// touch these implementation-specific methods.
- public String getPackageName()
+ public String getTargetName()
{
- return m_pkgName;
+ return m_targetName;
}
- public VersionRange getPackageVersionRange()
+ public VersionRange getTargetVersionRange()
{
- return m_pkgVersionRange;
+ return m_targetVersionRange;
}
public R4Directive[] getDirectives()