# HG changeset patch # Parent 7bde26a240db9cbb799fdaf3e9a9e3721a5937a1 Issue #157828: new client method ModuleInfo.forClass avoids linear search. diff --git a/core.osgi/src/org/netbeans/core/osgi/OSGiMainLookup.java b/core.osgi/src/org/netbeans/core/osgi/OSGiMainLookup.java --- a/core.osgi/src/org/netbeans/core/osgi/OSGiMainLookup.java +++ b/core.osgi/src/org/netbeans/core/osgi/OSGiMainLookup.java @@ -131,7 +131,7 @@ private void postInit() { nonClassLoaderDelegates.add(Lookups.fixed(OSGiRepository.DEFAULT, new OSGiLifecycleManager(context), new OSGiInstalledFileLocator(context))); nonClassLoaderDelegates.add(new AbstractLookup(moduleInfoContent)); - // XXX InstalledFileLocator impl for OSGI-INF/files/* + // XXX could add a ModuleInfo.OwnershipProvider setClassLoader(); } diff --git a/core.startup/src/org/netbeans/core/startup/preferences/PreferencesProviderImpl.java b/core.startup/src/org/netbeans/core/startup/preferences/PreferencesProviderImpl.java --- a/core.startup/src/org/netbeans/core/startup/preferences/PreferencesProviderImpl.java +++ b/core.startup/src/org/netbeans/core/startup/preferences/PreferencesProviderImpl.java @@ -45,7 +45,7 @@ package org.netbeans.core.startup.preferences; import java.util.prefs.Preferences; -import org.netbeans.Util; +import org.openide.modules.ModuleInfo; import org.openide.util.lookup.ServiceProvider; /** @@ -53,15 +53,11 @@ */ @ServiceProvider(service=org.openide.util.NbPreferences.Provider.class) public class PreferencesProviderImpl implements org.openide.util.NbPreferences.Provider { - /** Creates a new instance of PreferencesProviderImpl */ - public PreferencesProviderImpl() { - } - public Preferences preferencesForModule(Class cls) { String absolutePath = null; - ClassLoader cl = cls.getClassLoader(); - if (cl instanceof Util.ModuleProvider) { - absolutePath = ((Util.ModuleProvider) cl).getModule().getCodeNameBase(); + ModuleInfo owner = ModuleInfo.forClass(cls); + if (owner != null) { + absolutePath = owner.getCodeNameBase(); } else { absolutePath = cls.getName().replaceFirst("(^|\\.)[^.]+$", "");//NOI18N } diff --git a/o.n.bootstrap/src/org/netbeans/Module.java b/o.n.bootstrap/src/org/netbeans/Module.java --- a/o.n.bootstrap/src/org/netbeans/Module.java +++ b/o.n.bootstrap/src/org/netbeans/Module.java @@ -259,8 +259,7 @@ return specVers; } - @Override - public boolean owns(Class clazz) { + public @Override boolean owns(Class clazz) { ClassLoader cl = clazz.getClassLoader(); if (cl instanceof Util.ModuleProvider) { return ((Util.ModuleProvider) cl).getModule() == this; @@ -268,6 +267,14 @@ if (cl != classloader) { return false; } + String _codeName = findClasspathModuleCodeName(clazz); + if (_codeName != null) { + return _codeName.equals(codeName); + } + return true; // not sure... + } + + static String findClasspathModuleCodeName(Class clazz) { // #157798: in JNLP or otherwise classpath mode, all modules share a CL. CodeSource src = clazz.getProtectionDomain().getCodeSource(); if (src != null) { @@ -280,8 +287,7 @@ URL manifest = new URL(loc, "META-INF/MANIFEST.MF"); InputStream is = manifest.openStream(); try { - Manifest mf = new Manifest(is); - return codeName.equals(mf.getMainAttributes().getValue("OpenIDE-Module")); + return new Manifest(is).getMainAttributes().getValue("OpenIDE-Module"); } finally { is.close(); } @@ -289,7 +295,7 @@ Logger.getLogger(Module.class.getName()).log(Level.FINE, null, x); } } - return true; // not sure... + return null; } /** Get all packages exported by this module to other modules. diff --git a/o.n.bootstrap/src/org/netbeans/ModuleManager.java b/o.n.bootstrap/src/org/netbeans/ModuleManager.java --- a/o.n.bootstrap/src/org/netbeans/ModuleManager.java +++ b/o.n.bootstrap/src/org/netbeans/ModuleManager.java @@ -76,6 +76,8 @@ import org.openide.util.TopologicalSortException; import org.openide.util.Union2; import org.openide.util.Utilities; +import org.openide.util.lookup.Lookups; +import org.openide.util.lookup.ProxyLookup; /** Manages a collection of modules. * Must use {@link #mutex} to access its important methods. @@ -272,6 +274,19 @@ } private final Util.ModuleLookup lookup = new Util.ModuleLookup(); + private final Lookup completeLookup = new ProxyLookup(Lookups.fixed(new ModuleInfo.OwnershipProvider() { + public @Override ModuleInfo forClass(Class clazz) { + ClassLoader cl = clazz.getClassLoader(); + if (cl instanceof Util.ModuleProvider) { + return ((Util.ModuleProvider) cl).getModule(); + } + String codename = Module.findClasspathModuleCodeName(clazz); + if (codename != null) { + return get(codename.replaceFirst("/\\d+$", "")); // NOI18N + } + return null; + } + }), lookup); /** Retrieve set of modules in Lookup form. * The core top manager should install this into the set of * available lookups. Will fire lookup events when the @@ -281,7 +296,7 @@ * straight to this lookup when ModuleInfo/Module is requested. */ public Lookup getModuleLookup() { - return lookup; + return completeLookup; } // Access from ChangeFirer: final void fireModulesCreatedDeleted(Set created, Set deleted) { diff --git a/o.n.bootstrap/test/unit/src/org/netbeans/ModuleManagerTest.java b/o.n.bootstrap/test/unit/src/org/netbeans/ModuleManagerTest.java --- a/o.n.bootstrap/test/unit/src/org/netbeans/ModuleManagerTest.java +++ b/o.n.bootstrap/test/unit/src/org/netbeans/ModuleManagerTest.java @@ -2532,6 +2532,8 @@ TestFileUtils.writeFile(new File(data, "mod2/pkg/C3.java"), "package pkg; class C3 {}"); File mod2JAR = createTestJAR(data, jars, "mod2", null); ModuleManager mgr = new ModuleManager(new MockModuleInstaller(), new MockEvents()); + ModuleInfo.OwnershipProvider ownership = mgr.getModuleLookup().lookup(ModuleInfo.OwnershipProvider.class); + assertNotNull(ownership); mgr.mutexPrivileged().enterWriteAccess(); try { Module mod1 = mgr.create(mod1JAR, null, false, false, false); @@ -2547,10 +2549,16 @@ assertFalse(mod2.owns(c1)); assertFalse(mod2.owns(c2)); assertTrue(mod2.owns(c3)); + assertEquals(mod1, ownership.forClass(c1)); + assertEquals(mod1, ownership.forClass(c2)); + assertEquals(mod2, ownership.forClass(c3)); + assertNull(ownership.forClass(String.class)); } finally { mgr.mutexPrivileged().exitWriteAccess(); } mgr = new ModuleManager(new MockModuleInstaller(), new MockEvents()); + ownership = mgr.getModuleLookup().lookup(ModuleInfo.OwnershipProvider.class); + assertNotNull(ownership); mgr.mutexPrivileged().enterWriteAccess(); try { ClassLoader l = new URLClassLoader(new URL[] {mod1JAR.toURI().toURL(), mod2JAR.toURI().toURL()}); @@ -2569,6 +2577,10 @@ assertFalse(mod2.owns(c1)); assertFalse(mod2.owns(c2)); assertTrue(mod2.owns(c3)); + assertEquals(mod1, ownership.forClass(c1)); + assertEquals(mod1, ownership.forClass(c2)); + assertEquals(mod2, ownership.forClass(c3)); + assertNull(ownership.forClass(String.class)); } finally { mgr.mutexPrivileged().exitWriteAccess(); } diff --git a/o.n.core/src/org/netbeans/core/NbLoaderPool.java b/o.n.core/src/org/netbeans/core/NbLoaderPool.java --- a/o.n.core/src/org/netbeans/core/NbLoaderPool.java +++ b/o.n.core/src/org/netbeans/core/NbLoaderPool.java @@ -52,7 +52,6 @@ import java.io.OutputStream; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; @@ -317,9 +316,6 @@ oos.writeObject (new HashMap()/*installBefores*/); oos.writeObject (new HashMap()/*installAfters*/); - // Note which module each loader came from. - Collection modules = Lookup.getDefault().lookupAll(ModuleInfo.class); // Collection - Iterator it = loaders.iterator (); while (it.hasNext ()) { @@ -345,12 +341,9 @@ if (obj != null) { if (err.isLoggable(Level.FINE)) err.fine("writing modified " + l.getClass().getName()); // Find its module, if any. - Class c = l.getClass(); - Iterator mit = modules.iterator(); boolean found = false; - while (mit.hasNext()) { - ModuleInfo m = (ModuleInfo)mit.next(); - if (m.isEnabled() && m.owns(c)) { + ModuleInfo m = ModuleInfo.forClass(l.getClass()); + if (m != null && m.isEnabled()) { if (err.isLoggable(Level.FINE)) err.fine("belongs to module: " + m.getCodeNameBase()); oos.writeObject(m.getCodeNameBase()); int r = m.getCodeNameRelease(); @@ -362,8 +355,6 @@ oos.writeObject(null); } found = true; - break; - } } if (!found) { if (err.isLoggable(Level.FINE)) err.fine("does not belong to any module"); diff --git a/openide.loaders/src/org/openide/loaders/DataLoaderPool.java b/openide.loaders/src/org/openide/loaders/DataLoaderPool.java --- a/openide.loaders/src/org/openide/loaders/DataLoaderPool.java +++ b/openide.loaders/src/org/openide/loaders/DataLoaderPool.java @@ -568,18 +568,11 @@ fo.setAttribute(DataObject.EA_ASSIGNED_LOADER, null); } else { Class c = loader.getClass(); - // [PENDING] in the future a more efficient API may be introduced - Iterator modules = Lookup.getDefault().lookupAll(ModuleInfo.class).iterator(); - String modulename = null; - while (modules.hasNext()) { - ModuleInfo module = (ModuleInfo)modules.next(); - if (module.owns(c)) { - modulename = module.getCodeNameBase(); - break; - } + fo.setAttribute (DataObject.EA_ASSIGNED_LOADER, c.getName ()); + ModuleInfo module = ModuleInfo.forClass(c); + if (module != null) { + fo.setAttribute(DataObject.EA_ASSIGNED_LOADER_MODULE, module.getCodeNameBase()); } - fo.setAttribute (DataObject.EA_ASSIGNED_LOADER, c.getName ()); - fo.setAttribute(DataObject.EA_ASSIGNED_LOADER_MODULE, modulename); } if (!DataObjectPool.getPOOL().revalidate(Collections.singleton(fo)).isEmpty()) { DataObject.LOG.fine("It was not possible to invalidate data object: " + fo); // NOI18N diff --git a/openide.modules/src/org/openide/modules/ModuleInfo.java b/openide.modules/src/org/openide/modules/ModuleInfo.java --- a/openide.modules/src/org/openide/modules/ModuleInfo.java +++ b/openide.modules/src/org/openide/modules/ModuleInfo.java @@ -43,13 +43,10 @@ */ package org.openide.modules; -import java.beans.*; - -// THIS CLASS OUGHT NOT USE NbBundle NOR org.openide CLASSES -// OUTSIDE OF openide-util.jar! UI AND FILESYSTEM/DATASYSTEM -// INTERACTIONS SHOULD GO ELSEWHERE. -import java.util.*; - +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Set; +import org.openide.util.Lookup; /** General information about a module. * Immutable from an API perspective, serves as @@ -162,9 +159,31 @@ * was loaded as a part of this module, and thus will only be * loadable later if this module is enabled. * If in doubt, return false. + * @see #forClass * @since 1.28 */ public abstract boolean owns(Class clazz); + + /** + * Finds the module which loaded a class. + * @param clazz a class + * @return the owner of the class, or null if it is not owned by any module + * @see #owns + * @since XXX + */ + public static ModuleInfo forClass(Class clazz) { + OwnershipProvider prov = Lookup.getDefault().lookup(OwnershipProvider.class); + if (prov != null) { + return prov.forClass(clazz); + } else { + for (ModuleInfo module : Lookup.getDefault().lookupAll(ModuleInfo.class)) { + if (module.owns(clazz)) { + return module; + } + } + return null; + } + } /** * Get a class loader associated with this module that can load @@ -197,4 +216,21 @@ public String[] getProvides() { return new String[] { }; } + + /** + * Service implemented by module system to quickly look up the owner of a class. + * @see ModuleInfo#forClass + * @since XXX + */ + public interface OwnershipProvider { + + /** + * Finds the module which loaded a class. + * @param clazz a class + * @return the owner of the class, or null if it is not owned by any module + */ + ModuleInfo forClass(Class clazz); + + } + } diff --git a/refactoring.api/src/org/netbeans/modules/refactoring/api/AbstractRefactoring.java b/refactoring.api/src/org/netbeans/modules/refactoring/api/AbstractRefactoring.java --- a/refactoring.api/src/org/netbeans/modules/refactoring/api/AbstractRefactoring.java +++ b/refactoring.api/src/org/netbeans/modules/refactoring/api/AbstractRefactoring.java @@ -373,13 +373,9 @@ } } - private String getModuleName(Class c) { - for (ModuleInfo info:Lookup.getDefault().lookupAll(ModuleInfo.class)) { - if (info.owns(c)) { - return info.getDisplayName(); - } - } - return "Unknown";//NOI18N + private String getModuleName(Class c) { + ModuleInfo info = ModuleInfo.forClass(c); + return info != null ? info.getDisplayName() : "Unknown"; //NOI18N } private String createMessage(Class c, Throwable t) { diff --git a/settings/src/org/netbeans/modules/settings/convertors/ModuleInfoManager.java b/settings/src/org/netbeans/modules/settings/convertors/ModuleInfoManager.java --- a/settings/src/org/netbeans/modules/settings/convertors/ModuleInfoManager.java +++ b/settings/src/org/netbeans/modules/settings/convertors/ModuleInfoManager.java @@ -164,19 +164,6 @@ return reloaded; } - - /** look up ModuleInfo according to clazz - * @param clazz class used in the look up query - * @return module info of the module which clazz was loaded from - */ - public ModuleInfo getModuleInfo(Class clazz) { - Iterator it = getModulesResult().allInstances().iterator(); - while (it.hasNext()) { - ModuleInfo mi = (ModuleInfo) it.next(); - if (mi.owns(clazz)) return mi; - } - return null; - } /** register listener to be notified about changes of mi * @param sdc convertor diff --git a/settings/src/org/netbeans/modules/settings/convertors/SerialDataConvertor.java b/settings/src/org/netbeans/modules/settings/convertors/SerialDataConvertor.java --- a/settings/src/org/netbeans/modules/settings/convertors/SerialDataConvertor.java +++ b/settings/src/org/netbeans/modules/settings/convertors/SerialDataConvertor.java @@ -135,7 +135,7 @@ * @exception IOException if the object cannot be written */ public void write(Writer w, Object inst) throws IOException { - XMLSettingsSupport.storeToXML10(inst, w, ModuleInfoManager.getDefault().getModuleInfo(inst.getClass())); + XMLSettingsSupport.storeToXML10(inst, w, ModuleInfo.forClass(inst.getClass())); } /** delegate to SaveSupport to handle an unfired setting object change diff --git a/settings/src/org/netbeans/modules/settings/convertors/XMLSettingsSupport.java b/settings/src/org/netbeans/modules/settings/convertors/XMLSettingsSupport.java --- a/settings/src/org/netbeans/modules/settings/convertors/XMLSettingsSupport.java +++ b/settings/src/org/netbeans/modules/settings/convertors/XMLSettingsSupport.java @@ -1167,7 +1167,7 @@ } public void write(java.io.Writer w, Object inst) throws java.io.IOException { - XMLSettingsSupport.storeToXML10(inst, w, ModuleInfoManager.getDefault().getModuleInfo(inst.getClass())); + XMLSettingsSupport.storeToXML10(inst, w, ModuleInfo.forClass(inst.getClass())); } }