You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@netbeans.apache.org by GitBox <gi...@apache.org> on 2018/09/06 10:15:32 UTC

[GitHub] JaroslavTulach closed pull request #844: Enforce public packages and friends for dependencies on bootstrap mod…

JaroslavTulach closed pull request #844: Enforce public packages and friends for dependencies on bootstrap mod…
URL: https://github.com/apache/incubator-netbeans/pull/844
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/platform/core.startup.base/nbproject/project.properties b/platform/core.startup.base/nbproject/project.properties
index ef9483b053..7eb3ef96e4 100644
--- a/platform/core.startup.base/nbproject/project.properties
+++ b/platform/core.startup.base/nbproject/project.properties
@@ -21,6 +21,6 @@ module.jar.dir=core
 module.jar.basename=core-base.jar
 javadoc.arch=${basedir}/arch.xml
 
-test-unit-sys-prop.xtest.data=${nb_all}/o.n.bootstrap/test/unit/data
-test.unit.data.dir=${nb_all}/o.n.bootstrap/test/unit/data
+test-unit-sys-prop.xtest.data=${nb_all}/platform/o.n.bootstrap/test/unit/data
+test.unit.data.dir=${nb_all}/platform/o.n.bootstrap/test/unit/data
 
diff --git a/platform/core.startup/nbproject/project.properties b/platform/core.startup/nbproject/project.properties
index a0cb7ab24b..e1a0ef9eb4 100644
--- a/platform/core.startup/nbproject/project.properties
+++ b/platform/core.startup/nbproject/project.properties
@@ -24,8 +24,8 @@ module.jar.basename=core.jar
 spec.version.base=1.65.0
 
 # XXX using a data dir from another module means that these tests cannot be run from testdist
-test-unit-sys-prop.xtest.data=${nb_all}/o.n.bootstrap/test/unit/data
-test.unit.data.dir=${nb_all}/o.n.bootstrap/test/unit/data
+test-unit-sys-prop.xtest.data=${nb_all}/platform/o.n.bootstrap/test/unit/data
+test.unit.data.dir=${nb_all}/platform/o.n.bootstrap/test/unit/data
 
 test.config.stableBTD.includes=**/*Test.class
 test.config.stableBTD.excludes=\
diff --git a/platform/core.startup/src/org/netbeans/core/startup/ModuleSystem.java b/platform/core.startup/src/org/netbeans/core/startup/ModuleSystem.java
index 1938cba32d..a47ac7c9b9 100644
--- a/platform/core.startup/src/org/netbeans/core/startup/ModuleSystem.java
+++ b/platform/core.startup/src/org/netbeans/core/startup/ModuleSystem.java
@@ -40,17 +40,16 @@
 import java.util.logging.Logger;
 import org.netbeans.DuplicateException;
 import org.netbeans.Events;
+import org.netbeans.JarClassLoader;
 import org.netbeans.JaveleonModule;
 import org.netbeans.Module;
 import org.netbeans.ModuleManager;
 import org.netbeans.Stamps;
-import org.netbeans.TopSecurityManager;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileSystem;
 import org.openide.filesystems.FileUtil;
 import org.openide.modules.ModuleInfo;
 import org.openide.modules.OnStop;
-import org.openide.modules.Places;
 import org.openide.util.Exceptions;
 import org.openide.util.Utilities;
 
@@ -176,54 +175,23 @@ public void loadBootModules() {
         ev.log(Events.START_LOAD_BOOT_MODULES);
         try {
             bootModules = new HashSet<Module>(10);
-            ClassLoader loader = ModuleSystem.class.getClassLoader();
+            ClassLoader upperLoader = ModuleSystem.class.getClassLoader();
+            // wrap alien loader, so it can be used among parent loaders of module (instanceof ProxyClassLoader)
+            ClassLoader loader = new JarClassLoader(Collections.<File>emptyList(), new ClassLoader[] { Module.class.getClassLoader() });
+            
             Enumeration<URL> e = loader.getResources("META-INF/MANIFEST.MF"); // NOI18N
+            Enumeration<URL> upperE = upperLoader.getResources("META-INF/MANIFEST.MF"); // NOI18N
             ev.log(Events.PERF_TICK, "got all manifests"); // NOI18N
             
             // There will be duplicates: cf. #32576.
             Set<URL> checkedManifests = new HashSet<URL>();
-            MANIFESTS:
-            while (e.hasMoreElements()) {
-                URL manifestUrl = e.nextElement();
-                if (!checkedManifests.add(manifestUrl)) {
-                    // Already seen, ignore.
-                    continue;
-                }
-                URL jarURL = FileUtil.getArchiveFile(manifestUrl);
-                if (jarURL != null && jarURL.getProtocol().equals("file") &&
-                        /* #121777 */ jarURL.getPath().startsWith("/")) {
-                    LOG.log(Level.FINE, "Considering JAR: {0}", jarURL);
-                try {
-                        if (ignoredJars.contains(Utilities.toFile(jarURL.toURI()))) {
-                        LOG.log(Level.FINE, "ignoring JDK/JRE manifest: {0}", manifestUrl);
-                        continue MANIFESTS;
-                    }
-                } catch (URISyntaxException x) {
-                    Exceptions.printStackTrace(x);
-                }
-                }
-                LOG.log(Level.FINE, "Checking boot manifest: {0}", manifestUrl);
-                
-                InputStream is;
-                try {
-                    is = manifestUrl.openStream();
-                } catch (IOException ioe) {
-                    // Debugging for e.g. #32493 - which JAR was guilty?
-                    Exceptions.attachMessage(ioe, "URL: " + manifestUrl); // NOI18N
-                    throw ioe;
-                }
-                try {
-                    Manifest mani = new Manifest(is);
-                    Attributes attr = mani.getMainAttributes();
-                    if (attr.getValue("OpenIDE-Module") == null) { // NOI18N
-                        // Not a module.
-                        continue;
-                    }
-                    bootModules.add(mgr.createFixed(mani, manifestUrl, loader));
-                } finally {
-                    is.close();
-                }
-            }
+            
+            // process libs in 2 passes; first, process bootstrap libraries in platform/libs, creating
+            // FixedModules with a classloader that only loads from those libs.
+            // 2nd pass will process the remaining libraries, using this classloader.
+            createBootModules(e, checkedManifests, ignoredJars, loader);
+            createBootModules(upperE, checkedManifests, ignoredJars, upperLoader);
+
             if (list == null) {
                 // Plain calling us, we have to install now.
                 // Do it the simple way.
@@ -245,6 +213,60 @@ public void loadBootModules() {
             mgr.mutexPrivileged().exitWriteAccess();
         }
     }
+
+    /**
+     * Creates bootstrap (fixed) modules for the given manifests.
+     * 
+     * @param e manifest URLs.
+     * @param checkedManifests manifests already processed earlier
+     * @param ignoredJars JARs which should be ignored
+     * @param loader module classloader for the created modules
+     * 
+     * @throws IOException
+     * @throws DuplicateException 
+     */
+    private void createBootModules(Enumeration<URL> e, Set<URL> checkedManifests, Set<File> ignoredJars, ClassLoader loader) throws IOException, DuplicateException {
+        while (e.hasMoreElements()) {
+            URL manifestUrl = e.nextElement();
+            if (!checkedManifests.add(manifestUrl)) {
+                // Already seen, ignore.
+                continue;
+            }
+            URL jarURL = FileUtil.getArchiveFile(manifestUrl);
+            if (jarURL != null && jarURL.getProtocol().equals("file") &&
+                    /* #121777 */ jarURL.getPath().startsWith("/")) {
+                LOG.log(Level.FINE, "Considering JAR: {0}", jarURL);
+                try {
+                    if (ignoredJars.contains(Utilities.toFile(jarURL.toURI()))) {
+                        LOG.log(Level.FINE, "ignoring JDK/JRE manifest: {0}", manifestUrl);
+                        continue;
+                    }
+                } catch (URISyntaxException x) {
+                    Exceptions.printStackTrace(x);
+                }
+            }
+            LOG.log(Level.FINE, "Checking boot manifest: {0}", manifestUrl);
+            
+            InputStream is;
+            try {
+                is = manifestUrl.openStream();
+            } catch (IOException ioe) {
+                // Debugging for e.g. #32493 - which JAR was guilty?
+                throw Exceptions.attachMessage(ioe, "URL: " + manifestUrl); // NOI18N
+            }
+            try {
+                Manifest mani = new Manifest(is);
+                Attributes attr = mani.getMainAttributes();
+                if (attr.getValue("OpenIDE-Module") == null) { // NOI18N
+                    // Not a module.
+                    continue;
+                }
+                bootModules.add(mgr.createFixed(mani, manifestUrl, loader));
+            } finally {
+                is.close();
+            }
+        }
+    }
     
     /** Refreshes the list of modules. Used from autoupdate.services.
      * @since 1.28
diff --git a/platform/o.n.bootstrap/apichanges.xml b/platform/o.n.bootstrap/apichanges.xml
index 713c35a547..5c8dfa7538 100644
--- a/platform/o.n.bootstrap/apichanges.xml
+++ b/platform/o.n.bootstrap/apichanges.xml
@@ -29,6 +29,25 @@
   </apidefs>
 
   <changes>
+    <change id="bootstrap.filter">
+        <api name="launcher"/>
+        <summary>Can use classloader to check access to bootstrap classes</summary>
+        <version major="2" minor="80"/>
+        <date day="5" month="9" year="2018"/>
+        <author login="sdedic"/>
+        <compatibility addition="yes" binary="compatible" semantic="incompatible" deprecation="yes"/>
+        <description>
+            <p>
+                Bootstrap classloaders are not paired with a single module, yet they should obey visibility restrictions. The added method
+                allows to check also accesses to resources served by bootstrap classloaders.
+            </p>
+            <p>
+                This change <b>will hide classes</b> (namely <code>org.objectweb.asm</code>, but also some core impl classes) that were visible
+                in Apache NetBeans 9.0 release from NetBeans platform applications.
+            </p>
+        </description>
+        <class package="org.netbeans" name="ModuleManager"/>
+    </change>
     <change id="module.fragments">
          <api name="launcher"/>
          <summary>Ability to join other module</summary>
diff --git a/platform/o.n.bootstrap/manifest.mf b/platform/o.n.bootstrap/manifest.mf
index 3bab9b87a3..5c0c0bdd37 100644
--- a/platform/o.n.bootstrap/manifest.mf
+++ b/platform/o.n.bootstrap/manifest.mf
@@ -1,6 +1,6 @@
 Manifest-Version: 1.0
 OpenIDE-Module: org.netbeans.bootstrap/1
-OpenIDE-Module-Specification-Version: 2.79
+OpenIDE-Module-Specification-Version: 2.80
 OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
 OpenIDE-Module-Recommends: org.netbeans.NetigsoFramework
 
diff --git a/platform/o.n.bootstrap/src/org/netbeans/ModuleManager.java b/platform/o.n.bootstrap/src/org/netbeans/ModuleManager.java
index ce91d887dc..1a602d91b0 100644
--- a/platform/o.n.bootstrap/src/org/netbeans/ModuleManager.java
+++ b/platform/o.n.bootstrap/src/org/netbeans/ModuleManager.java
@@ -29,6 +29,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectOutputStream;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.net.URL;
 import java.security.AllPermission;
 import java.security.CodeSource;
@@ -50,11 +52,11 @@
 import java.util.Set;
 import java.util.StringTokenizer;
 import java.util.TreeSet;
+import java.util.WeakHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.jar.Manifest;
 import java.util.logging.Level;
-import java.util.logging.Logger;
 import org.openide.modules.Dependency;
 import org.openide.modules.ModuleInfo;
 import org.openide.modules.Modules;
@@ -91,6 +93,12 @@
     private final Set<Module> modules = new HashSet<Module>(100);
     // the same, indexed by code name base
     private final Map<String,Module> modulesByName = new HashMap<String,Module>(100);
+    
+    /**
+     * Registers classloaders and module objects for bootstrap modules.
+     */
+    // @GuardedBy(this)
+    private final Map<ClassLoader, Collection<Reference<Module>>> bootstrapModules = new WeakHashMap<>();
 
     /**
      * Modules whose contents is injected into 
@@ -848,6 +856,23 @@ public Module createFixed(Manifest mani, Object history, ClassLoader loader, boo
         Module m = moduleFactory.createFixed(mani, history, loader, autoload, eager, this, ev);
         ev.log(Events.FINISH_CREATE_BOOT_MODULE, history);
         subCreate(m);
+        synchronized (this) {
+            Collection<Reference<Module>> oldMods = bootstrapModules.get(loader);
+            Collection<Reference<Module>> mods;
+            if (oldMods == null) {
+                mods = new ArrayList<>();
+            } else {
+                mods = new ArrayList<>(oldMods);
+                for (Iterator<Reference<Module>> rit = mods.iterator(); rit.hasNext(); ) {
+                    Reference<Module> r = rit.next();
+                    if (r.get() == null) {
+                        rit.remove();
+                    }
+                }
+            }
+            mods.add(new WeakReference<>(m));
+            bootstrapModules.put(loader, mods);
+        }
         return m;
     }
 
@@ -906,11 +931,71 @@ void refineModulePath(Module m, List<File> path) {
             path.addAll(allJars);
         }
     }
-    
-    /** Use by OneModuleClassLoader to communicate with the ModuleInstaller re. masking. */
+
+    /** Use by OneModuleClassLoader to communicate with the ModuleInstaller re. masking. 
+     * @deprecated Use {@link #shouldDelegateResource(org.netbeans.Module, org.netbeans.Module, java.lang.String, java.lang.ClassLoader)}.
+     */
+    @Deprecated
     public boolean shouldDelegateResource(Module m, Module parent, String pkg) {
+        return shouldDelegateResource(m, parent, pkg, null);
+    }
+    
+    /**
+     * Determines if module `m' should delegate loading resources from package `p' to the
+     * `parent'. The parent is identified either by module specification (parent) or by a classloader
+     * which should load the package. For system or bootstrap classes, `parent' may be {@code null}, since
+     * boostrap classloaders load more modules together.
+     * <p/>
+     * If <b>both</b> `parent' and `ldr' are {@code null}, access to system/application classpath will be checked.
+     * 
+     * @param m module that attempts to load resources.
+     * @param parent parent classloader which may eventually load the resource, could be {@code null} to indicate bootstrap or system class
+     * @param pkg package (folder) with the resource
+     * @param ldr the classloader which should load the resource; may be {@code null}
+     * @return true, if the loading should be delegated to the classloader
+     * @since 2.80
+     */
+    public boolean shouldDelegateResource(Module m, Module parent, String pkg, ClassLoader ldr) {
         // Cf. #19621:
-        Module.PackageExport[] exports = (parent == null) ? null : parent.getPublicPackages();
+        Module.PackageExport[] exports;
+        if (parent != null) {
+            exports = parent.getPublicPackages();
+        } else if (ldr != null) {
+            Collection<Module> loaderMods = null;
+            synchronized (this) {
+                // create exports from modules for that classloader
+                Collection<Reference<Module>> refMods = bootstrapModules.get(ldr);
+                if (refMods != null) {
+                    loaderMods = new HashSet<>();
+                    for (Iterator<Reference<Module>> rmit = refMods.iterator(); rmit.hasNext(); ) {
+                        Reference<Module> refMod = rmit.next();
+                        Module mm = refMod.get();
+                        if (mm == null) {
+                            rmit.remove();
+                        } else {
+                            loaderMods.add(mm);
+                        }
+                    }
+                }
+            }
+            Set<String> cbn = new HashSet<>();
+            for (Dependency d : m.getDependenciesArray()) {
+                if (d.getType() == Dependency.TYPE_MODULE) {
+                    cbn.add(d.getName());
+                }
+            }
+            if (loaderMods != null) {
+                for (Module lm : loaderMods) {
+                    if (cbn.remove(lm.getCodeName()) && shouldDelegateResource(m, lm, pkg, ldr)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+            exports = null;
+        } else {
+            exports = null;
+        }
         if (exports != null) {
             //Util.err.fine("exports=" + Arrays.asList(exports));
             // Packages from parent are restricted: #19621.
diff --git a/platform/o.n.bootstrap/src/org/netbeans/StandardModule.java b/platform/o.n.bootstrap/src/org/netbeans/StandardModule.java
index 8c2f51f5ca..52ab00b697 100644
--- a/platform/o.n.bootstrap/src/org/netbeans/StandardModule.java
+++ b/platform/o.n.bootstrap/src/org/netbeans/StandardModule.java
@@ -687,7 +687,7 @@ public Module getModule() {
             } else {
                 other = null;
             }
-            return getManager().shouldDelegateResource(StandardModule.this, other, pkg);
+            return getManager().shouldDelegateResource(StandardModule.this, other, pkg, parent);
         }
         
         public @Override String toString() {


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@netbeans.apache.org
For additional commands, e-mail: notifications-help@netbeans.apache.org

For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists