Author: pauls Date: Sun Sep 16 12:53:22 2007 New Revision: 576161 URL: http://svn.apache.org/viewvc?rev=576161&view=rev Log: Fix a few issues with exporting the same package more then once and handle modified module definitions to make extension bundle exports work again (FELIX-30, FELIX-101).
Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java?rev=576161&r1=576160&r2=576161&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/Felix.java Sun Sep 16 12:53:22 2007 @@ -40,7 +40,7 @@ // The extension manager to handle extension bundles private ExtensionManager m_extensionManager; - + // Logging related member variables. private Logger m_logger = null; // TODO: KARL - Why package private? // Immutable config properties. @@ -265,7 +265,7 @@ m_factory = new ModuleFactoryImpl(m_logger); m_systemBundleInfo = new BundleInfo( m_logger, new SystemBundleArchive(m_cache), null); - m_extensionManager = + m_extensionManager = new ExtensionManager(m_logger, m_configMap, m_systemBundleInfo); m_systemBundleInfo.addModule( m_factory.createModule("0", m_extensionManager)); @@ -783,7 +783,7 @@ // bundle ID from persistent storage. In case of failure, we should // keep the max value. m_nextId = Math.max(m_nextId, loadNextId()); - + // Get the framework's default start level. int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL; String s = (String) m_configMap.get(FelixConstants.FRAMEWORK_STARTLEVEL_PROP); @@ -1727,7 +1727,7 @@ new AdminPermission(bundle, AdminPermission.LIFECYCLE)); } - // We need to check whether this is an update to an + // We need to check whether this is an update to an // extension bundle (info.isExtension) or an update from // a normal bundle to an extension bundle // (isExtensionBundle()) @@ -1744,12 +1744,13 @@ // If this is an update from a normal to an extension bundle // then attach the extension or else if this already is - // an extension bundle then done allow it to be resolved + // an extension bundle then done allow it to be resolved // again as per spec. if (!bundle.getInfo().isExtension() && m_extensionManager.isExtensionBundle(bundle.getInfo().getCurrentHeader())) { m_extensionManager.addExtensionBundle(this, bundle); + m_factory.refreshModule(m_systemBundleInfo.getCurrentModule()); bundle.getInfo().setState(Bundle.RESOLVED); } else if (bundle.getInfo().isExtension()) @@ -1803,9 +1804,12 @@ for (int i = 0; !used && (i < modules.length); i++) { IModule[] dependents = ((ModuleImpl) modules[i]).getDependents(); - if ((dependents != null) && (dependents.length > 0)) + for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++) { - used = true; + if (dependents[j] != modules[i]) + { + used = true; + } } } @@ -2065,9 +2069,12 @@ for (int i = 0; !used && (i < modules.length); i++) { IModule[] dependents = ((ModuleImpl) modules[i]).getDependents(); - if ((dependents != null) && (dependents.length > 0)) + for (int j = 0; (dependents != null) && (j < dependents.length) && !used; j++) { - used = true; + if (dependents[j] != modules[i]) + { + used = true; + } } } @@ -2239,6 +2246,7 @@ else { m_extensionManager.addExtensionBundle(this, bundle); + m_factory.refreshModule(m_systemBundleInfo.getCurrentModule()); } } @@ -2289,8 +2297,8 @@ { m_installedBundleMap.put(location, bundle); } - - if (bundle.getInfo().isExtension()) + + if (bundle.getInfo().isExtension()) { FelixBundle systemBundle = (FelixBundle) getBundle(0); acquireBundleLock(systemBundle); @@ -2852,8 +2860,6 @@ **/ protected ExportedPackage[] getExportedPackages(String pkgName) { - ExportedPackage[] pkgs = null; - // First, get all exporters of the package. R4SearchPolicyCore.PackageSource[] exporters = m_policyCore.getInUseCandidates( @@ -2865,8 +2871,14 @@ if (exporters != null) { - pkgs = new ExportedPackage[exporters.length]; - for (int pkgIdx = 0; pkgIdx < pkgs.length; pkgIdx++) + List pkgs = new ArrayList(); + + Requirement req = new Requirement(ICapability.PACKAGE_NAMESPACE, + null, + null, + new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) }); + + for (int pkgIdx = 0; pkgIdx < exporters.length; pkgIdx++) { // Get the bundle associated with the current exporting module. FelixBundle bundle = (FelixBundle) getBundle( @@ -2885,25 +2897,22 @@ IModule[] modules = bundle.getInfo().getModules(); for (int modIdx = 0; modIdx < modules.length; modIdx++) { - Capability ec = (Capability) - Util.getSatisfyingCapability( - modules[modIdx], - new Requirement( - ICapability.PACKAGE_NAMESPACE, - null, - null, - new R4Attribute[] { new R4Attribute(ICapability.PACKAGE_PROPERTY, pkgName, false) })); - - if (ec != null) + ICapability[] ec = modules[modIdx].getDefinition().getCapabilities(); + for (int i = 0; (ec != null) && (i < ec.length); i++) { - pkgs[pkgIdx] = - new ExportedPackageImpl(this, bundle, modules[modIdx], ec); + if (ec[i].getNamespace().equals(req.getNamespace()) && + req.isSatisfied(ec[i])) + { + pkgs.add(new ExportedPackageImpl(this, bundle, modules[modIdx], (Capability) ec[i])); + } } } } + + return (pkgs.isEmpty()) ? null : (ExportedPackage[]) pkgs.toArray(new ExportedPackage[pkgs.size()]); } - return pkgs; + return null; } /** @@ -3060,7 +3069,12 @@ // package. If so, see if the provider module is from the // exporter and record it if it is. IWire wire = Util.getWire(depModules[depIdx], ep.getName()); - if ((wire != null) && expModules[expIdx].equals(wire.getExporter())) + if ((wire != null) && expModules[expIdx].equals(wire.getExporter()) && + wire.getRequirement().isSatisfied( + new Capability(ICapability.PACKAGE_NAMESPACE, null, new R4Attribute[] { + new R4Attribute(ICapability.PACKAGE_PROPERTY, ep.getName(), false), + new R4Attribute(ICapability.VERSION_PROPERTY, ep.getVersion(), false) + }))) { // Add the bundle to the list of importers. list.add(getBundle(Util.getBundleIdFromModuleId(depModules[depIdx].getId()))); @@ -3121,7 +3135,7 @@ FelixBundle[] bundles = acquireBundleRefreshLocks(targets); boolean restart = false; - + Bundle systemBundle = getBundle(0); // We need to restart the framework if either an extension bundle is Modified: felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java URL: http://svn.apache.org/viewvc/felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java?rev=576161&r1=576160&r2=576161&view=diff ============================================================================== --- felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java (original) +++ felix/trunk/framework/src/main/java/org/apache/felix/framework/searchpolicy/R4SearchPolicyCore.java Sun Sep 16 12:53:22 2007 @@ -780,6 +780,7 @@ { String pkgName = ((Requirement) req).getPackageName(); IModule[] modules = (IModule[]) m_inUsePkgIndexMap.get(pkgName); + for (int modIdx = 0; (modules != null) && (modIdx < modules.length); modIdx++) { ICapability inUseCap = Util.getSatisfyingCapability(modules[modIdx], req); @@ -2456,6 +2457,64 @@ } } + /** + * This is an experimental method that is likely to change or go + * away - so don't use it for now. + * + * Note to self, we need to think about what the implications of + * this are and whether we are fine with them. + */ + /* + * This method is used by the framework to let us know that we need to re-read + * the system bundle capabilities which have been extended by an extension bundle. + * + * For now we assume that capabilities have been added only. We might need to + * enforce that at one point of time. + */ + public void moduleRefreshed(ModuleEvent event) + { + synchronized (m_factory) + { + IModule module = event.getModule(); + // Remove exports from package maps. + ICapability[] caps = event.getModule().getDefinition().getCapabilities(); + // Add exports to available package map. + for (int i = 0; (caps != null) && (i < caps.length); i++) + { + if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)) + { + indexPackageCapability(m_availPkgIndexMap, module, caps[i]); + } + + + ICapability[] inUseCaps = (ICapability[]) m_inUseCapMap.get(module); + inUseCaps = addCapabilityToArray(inUseCaps, caps[i]); + m_inUseCapMap.put(module, inUseCaps); + + // If the capability is a package, then add the exporter module + // of the wire to the "in use" package index and remove it + // from the "available" package index. + if (caps[i].getNamespace().equals(ICapability.PACKAGE_NAMESPACE)) + { + // Get package name. + String pkgName = (String) + caps[i].getProperties().get(ICapability.PACKAGE_PROPERTY); + // Add to "in use" package index. + indexPackageCapability( + m_inUsePkgIndexMap, + module, + caps[i]); + // Remove from "available" package index. + m_availPkgIndexMap.put( + pkgName, + removeModuleFromArray( + (IModule[]) m_availPkgIndexMap.get(pkgName), + module)); + } + } + } + } + private void indexPackageCapability(Map map, IModule module, ICapability capability) { if (capability.getNamespace().equals(ICapability.PACKAGE_NAMESPACE)) @@ -2579,35 +2638,39 @@ } int idx = -1; - for (int i = 0; i < modules.length; i++) + do { - if (modules[i] == m) + idx = -1; + for (int i = 0; i < modules.length; i++) { - idx = i; - break; + if (modules[i] == m) + { + idx = i; + break; + } } - } - if (idx >= 0) - { - // If this is the module, then point to empty list. - if ((modules.length - 1) == 0) - { - modules = m_emptyModules; - } - // Otherwise, we need to do some array copying. - else + if (idx >= 0) { - IModule[] newModules = new IModule[modules.length - 1]; - System.arraycopy(modules, 0, newModules, 0, idx); - if (idx < newModules.length) + // If this is the module, then point to empty list. + if ((modules.length - 1) == 0) { - System.arraycopy( - modules, idx + 1, newModules, idx, newModules.length - idx); + modules = m_emptyModules; + } + // Otherwise, we need to do some array copying. + else + { + IModule[] newModules = new IModule[modules.length - 1]; + System.arraycopy(modules, 0, newModules, 0, idx); + if (idx < newModules.length) + { + System.arraycopy( + modules, idx + 1, newModules, idx, newModules.length - idx); + } + modules = newModules; } - modules = newModules; } - } + } while (idx >= 0); return modules; }