This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 34699
Collapse All | Expand All

(-)openide/modules/src/org/openide/modules/Dependency.java (+12 lines)
Lines 47-52 Link Here
47
     */
47
     */
48
    public final static int TYPE_REQUIRES = 5;
48
    public final static int TYPE_REQUIRES = 5;
49
49
50
    /** Dependency on a token, but without need to have token provider be initialised sooner.
51
     * @see ModuleInfo#getProvides
52
     * @since JST-PENDING
53
     */
54
    public final static int TYPE_NEEDS = 6;
55
50
    /** Comparison by specification version. */
56
    /** Comparison by specification version. */
51
    public final static int COMPARE_SPEC = 1;
57
    public final static int COMPARE_SPEC = 1;
52
58
Lines 310-315 Link Here
310
            } else if (type == Dependency.TYPE_REQUIRES) {
316
            } else if (type == Dependency.TYPE_REQUIRES) {
311
                if (comparison != Dependency.COMPARE_ANY) {
317
                if (comparison != Dependency.COMPARE_ANY) {
312
                    throw new IllegalArgumentException("Cannot give a comparison for a token requires dep: " + body); // NOI18N
318
                    throw new IllegalArgumentException("Cannot give a comparison for a token requires dep: " + body); // NOI18N
319
                }
320
321
                checkCodeName(name, false);
322
            } else if (type == Dependency.TYPE_NEEDS) {
323
                if (comparison != Dependency.COMPARE_ANY) {
324
                    throw new IllegalArgumentException("Cannot give a comparison for a token needs dep: " + body); // NOI18N
313
                }
325
                }
314
326
315
                checkCodeName(name, false);
327
                checkCodeName(name, false);
(-)core/bootstrap/src/org/netbeans/Module.java (+1 lines)
Lines 393-398 Link Here
393
                dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
393
                dependencies.addAll(Dependency.create(Dependency.TYPE_PACKAGE, pkgdeps)); // NOI18N
394
            }
394
            }
395
            dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
395
            dependencies.addAll(Dependency.create(Dependency.TYPE_REQUIRES, attr.getValue("OpenIDE-Module-Requires"))); // NOI18N
396
            dependencies.addAll(Dependency.create(Dependency.TYPE_NEEDS, attr.getValue("OpenIDE-Module-Needs"))); // NOI18N
396
            // Permit the concrete installer to make some changes:
397
            // Permit the concrete installer to make some changes:
397
            mgr.refineDependencies(this, dependencies);
398
            mgr.refineDependencies(this, dependencies);
398
            dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]);
399
            dependenciesA = dependencies.toArray(new Dependency[dependencies.size()]);
(-)core/bootstrap/src/org/netbeans/ModuleManager.java (-7 / +11 lines)
Lines 1039-1045 Link Here
1039
                Util.err.log(Level.WARNING, null, ex);
1039
                Util.err.log(Level.WARNING, null, ex);
1040
            }
1040
            }
1041
            Util.err.warning("Cyclic module dependencies, will refuse to enable: " + deps); // NOI18N
1041
            Util.err.warning("Cyclic module dependencies, will refuse to enable: " + deps); // NOI18N
1042
            return Collections.<Module>emptyList();
1042
            return (List<Module>)ex.partialSort();
1043
        }
1043
        }
1044
    }
1044
    }
1045
    private void maybeAddToEnableList(Set<Module> willEnable, Set<Module> mightEnable, Module m, boolean okToFail) {
1045
    private void maybeAddToEnableList(Set<Module> willEnable, Set<Module> mightEnable, Module m, boolean okToFail) {
Lines 1065-1071 Link Here
1065
                if (! other.isEnabled()) {
1065
                if (! other.isEnabled()) {
1066
                    maybeAddToEnableList(willEnable, mightEnable, other, false);
1066
                    maybeAddToEnableList(willEnable, mightEnable, other, false);
1067
                }
1067
                }
1068
            } else if (dep.getType() == Dependency.TYPE_REQUIRES) {
1068
            } else if (dep.getType() == Dependency.TYPE_REQUIRES || dep.getType() == Dependency.TYPE_NEEDS) {
1069
                String token = dep.getName();
1069
                String token = dep.getName();
1070
                Set<Module> providers = providersOf.get(token);
1070
                Set<Module> providers = providersOf.get(token);
1071
                if (providers == null) throw new IllegalStateException("Should have found a provider of: " + token); // NOI18N
1071
                if (providers == null) throw new IllegalStateException("Should have found a provider of: " + token); // NOI18N
Lines 1309-1318 Link Here
1309
        // where moduleProblems are used are write-mutex only and so do not have
1309
        // where moduleProblems are used are write-mutex only and so do not have
1310
        // to worry about contention.
1310
        // to worry about contention.
1311
        synchronized (moduleProblems) {
1311
        synchronized (moduleProblems) {
1312
            return _missingDependencies(probed);
1312
            return _missingDependencies(probed, true);
1313
        }
1313
        }
1314
    }
1314
    }
1315
    private Set<Union2<Dependency,InvalidException>> _missingDependencies(Module probed) {
1315
    private Set<Union2<Dependency,InvalidException>> _missingDependencies(Module probed, boolean testCycle) {
1316
            Set<Union2<Dependency,InvalidException>> probs = moduleProblems.get(probed);
1316
            Set<Union2<Dependency,InvalidException>> probs = moduleProblems.get(probed);
1317
            if (probs == null) {
1317
            if (probs == null) {
1318
                probs = new HashSet<Union2<Dependency,InvalidException>>(8);
1318
                probs = new HashSet<Union2<Dependency,InvalidException>>(8);
Lines 1382-1388 Link Here
1382
                        if (! other.isEnabled()) {
1382
                        if (! other.isEnabled()) {
1383
                            // Need to make sure the other one is not missing anything either.
1383
                            // Need to make sure the other one is not missing anything either.
1384
                            // Nor that it depends (directly on indirectly) on this one.
1384
                            // Nor that it depends (directly on indirectly) on this one.
1385
                            if (! _missingDependencies(other).isEmpty()) {
1385
                            if (! _missingDependencies(other, testCycle).isEmpty()) {
1386
                                // This is a little subtle. Either the other module had real
1386
                                // This is a little subtle. Either the other module had real
1387
                                // problems, in which case our dependency on it is not legit.
1387
                                // problems, in which case our dependency on it is not legit.
1388
                                // Or, the other actually depends cyclically on this one. In
1388
                                // Or, the other actually depends cyclically on this one. In
Lines 1401-1407 Link Here
1401
                            // on it if we need it.
1401
                            // on it if we need it.
1402
                        }
1402
                        }
1403
                        // Already-installed modules are of course fine.
1403
                        // Already-installed modules are of course fine.
1404
                    } else if (dep.getType() == Dependency.TYPE_REQUIRES) {
1404
                    } else if (dep.getType() == Dependency.TYPE_REQUIRES || dep.getType() == Dependency.TYPE_NEEDS) {
1405
                        // Works much like a regular module dependency. However it only
1405
                        // Works much like a regular module dependency. However it only
1406
                        // fails if there are no satisfying modules with no problems.
1406
                        // fails if there are no satisfying modules with no problems.
1407
                        String token = dep.getName();
1407
                        String token = dep.getName();
Lines 1416-1422 Link Here
1416
                                if (other.isEnabled()) {
1416
                                if (other.isEnabled()) {
1417
                                    foundOne = true;
1417
                                    foundOne = true;
1418
                                } else {
1418
                                } else {
1419
                                    if (_missingDependencies(other).isEmpty()) {
1419
                                    if (_missingDependencies(other, testCycle && dep.getType() == Dependency.TYPE_REQUIRES).isEmpty()) {
1420
                                        // See comment above for regular module deps
1420
                                        // See comment above for regular module deps
1421
                                        // re. use of PROBING_IN_PROCESS.
1421
                                        // re. use of PROBING_IN_PROCESS.
1422
                                        foundOne = true;
1422
                                        foundOne = true;
Lines 1438-1443 Link Here
1438
                    }
1438
                    }
1439
                }
1439
                }
1440
                probs.remove(PROBING_IN_PROCESS);
1440
                probs.remove(PROBING_IN_PROCESS);
1441
            } else {
1442
                if (!testCycle && probs.size() == 1 && probs.iterator().next() == PROBING_IN_PROCESS) {
1443
                    return Collections.emptySet();
1444
                }
1441
            }
1445
            }
1442
            return probs;
1446
            return probs;
1443
    }
1447
    }
(-)core/bootstrap/src/org/netbeans/Util.java (-1 / +1 lines)
Lines 366-372 Link Here
366
            for (int i = 0; i < dependencies.length; i++) {
366
            for (int i = 0; i < dependencies.length; i++) {
367
                Dependency dep = dependencies[i];
367
                Dependency dep = dependencies[i];
368
368
369
                if (dep.getType() == Dependency.TYPE_REQUIRES) {
369
                if (dep.getType() == Dependency.TYPE_REQUIRES || dep.getType() == Dependency.TYPE_NEEDS) {
370
                    List<Module> providers = providersOf.get(dep.getName());
370
                    List<Module> providers = providersOf.get(dep.getName());
371
371
372
                    if (providers != null) {
372
                    if (providers != null) {
(-)core/startup/test/unit/src/org/netbeans/core/startup/ModuleManagerTest.java (+83 lines)
Lines 49-54 Link Here
49
import org.openide.util.Lookup;
49
import org.openide.util.Lookup;
50
import org.openide.util.LookupEvent;
50
import org.openide.util.LookupEvent;
51
import org.openide.util.LookupListener;
51
import org.openide.util.LookupListener;
52
import org.openide.util.TopologicalSortException;
52
import org.openide.util.Utilities;
53
import org.openide.util.Utilities;
53
54
54
/** Test the module manager as well as the Module class.
55
/** Test the module manager as well as the Module class.
Lines 1018-1023 Link Here
1018
            assertEquals(4, toEnable.size());
1019
            assertEquals(4, toEnable.size());
1019
            assertTrue(toEnable.get(0) != m2);
1020
            assertTrue(toEnable.get(0) != m2);
1020
            assertTrue(toEnable.get(0) != m3);
1021
            assertTrue(toEnable.get(0) != m3);
1022
        } finally {
1023
            mgr.mutexPrivileged().exitWriteAccess();
1024
        }
1025
    }
1026
    
1027
    public void testSimpleProvNeeds() throws Exception {
1028
        FakeModuleInstaller installer = new FakeModuleInstaller();
1029
        FakeEvents ev = new FakeEvents();
1030
        ModuleManager mgr = new ModuleManager(installer, ev);
1031
        mgr.mutexPrivileged().enterWriteAccess();
1032
        try {
1033
            Module m1 = mgr.create(new File(jars, "prov-foo-depends-needs_foo.jar"), null, false, false, false);
1034
            Module m2 = mgr.create(new File(jars, "needs-foo.jar"), null, false, false, false);
1035
            assertEquals(Collections.singletonList("foo"), Arrays.asList(m1.getProvides()));
1036
            assertEquals(Collections.EMPTY_LIST, Arrays.asList(m2.getProvides()));
1037
            assertEquals(1, m1.getDependencies().size());
1038
            assertEquals(Dependency.create(Dependency.TYPE_NEEDS, "foo"), m2.getDependencies());
1039
            Map<String,Module> modulesByName = new HashMap<String,Module>();
1040
            modulesByName.put(m1.getCodeNameBase(), m1);
1041
            modulesByName.put(m2.getCodeNameBase(), m2);
1042
            Map<String,Set<Module>> providersOf = new HashMap<String,Set<Module>>();
1043
            providersOf.put("foo", Collections.singleton(m1));
1044
            List<Module> m1m2 = Arrays.asList(new Module[] {m1, m2});
1045
            List<Module> m2m1 = Arrays.asList(new Module[] {m2, m1});
1046
            Map<Module,List<Module>> deps = Util.moduleDependencies(m1m2, modulesByName, providersOf);
1047
            assertEquals(Collections.singletonList(m2), deps.get(m1));
1048
            assertEquals(Collections.singletonList(m1), deps.get(m2));
1049
            
1050
            try {
1051
                Utilities.topologicalSort(m1m2, deps);
1052
            } catch (TopologicalSortException ex) {
1053
                Set[] arr = ex.unsortableSets();
1054
                assertEquals("One unsortable set", 1, arr.length);
1055
                assertEquals("It contains two elements", 2, arr[0].size());
1056
                assertTrue("m1 is there", arr[0].contains(m1));
1057
                assertTrue("m2 is there", arr[0].contains(m2));
1058
            }
1059
            Set<Module> m1PlusM2 = new HashSet<Module>();
1060
            m1PlusM2.add(m1);
1061
            m1PlusM2.add(m2);
1062
            List<Module> toEnable = mgr.simulateEnable(m1PlusM2);
1063
            assertEquals("correct result of simulateEnable", Arrays.asList(new Module[] {m2, m1}), toEnable);
1064
            toEnable = mgr.simulateEnable(Collections.singleton(m1));
1065
            assertEquals("correct result of simulateEnable #2", Arrays.asList(new Module[] {m2, m1}), toEnable);
1066
            toEnable = mgr.simulateEnable(Collections.singleton(m2));
1067
            assertEquals("correct result of simulateEnable #3", Arrays.asList(new Module[] {m2, m1}), toEnable);
1068
            mgr.enable(m1PlusM2);
1069
            assertEquals(Arrays.asList(new String[] {
1070
                "prepare",
1071
                "prepare",
1072
                "load"
1073
            }), installer.actions);
1074
            assertEquals(Arrays.asList(new Object[] {
1075
                m1,
1076
                m2,
1077
                Arrays.asList(new Module[] {m1, m2})
1078
            }), installer.args);
1079
            Class testclazz = Class.forName("org.prov_foo.Clazz", true, m1.getClassLoader());
1080
            try {
1081
                Class.forName("org.prov_foo.Clazz", true, m2.getClassLoader());
1082
                fail("Should not be able to access classes due to prov-req deps only");
1083
            } catch (ClassNotFoundException cnfe) {
1084
                // OK, good.
1085
            }
1086
            installer.clear();
1087
            List<Module> toDisable = mgr.simulateDisable(Collections.singleton(m1));
1088
            assertEquals("correct result of simulateDisable", Arrays.asList(new Module[] {m2, m1}), toDisable);
1089
            toDisable = mgr.simulateDisable(m1PlusM2);
1090
            assertEquals("correct result of simulateDisable #2", Arrays.asList(new Module[] {m2, m1}), toDisable);
1091
            mgr.disable(m1PlusM2);
1092
            assertFalse(m1.isEnabled());
1093
            assertFalse(m2.isEnabled());
1094
            assertEquals(Arrays.asList(new String[] {
1095
                "unload",
1096
                "dispose",
1097
                "dispose"
1098
            }), installer.actions);
1099
            assertEquals(Arrays.asList(new Object[] {
1100
                Arrays.asList(new Module[] {m2, m1}),
1101
                m2,
1102
                m1
1103
            }), installer.args);
1021
        } finally {
1104
        } finally {
1022
            mgr.mutexPrivileged().exitWriteAccess();
1105
            mgr.mutexPrivileged().exitWriteAccess();
1023
        }
1106
        }
(-)core/startup/test/unit/src/org/netbeans/core/startup/build.xml (+2 lines)
Lines 152-157 Link Here
152
        <jar jarfile="jars/dep-on-relvertest-3-4.jar" manifest="jars/dep-on-relvertest-3-4.mf"/>
152
        <jar jarfile="jars/dep-on-relvertest-3-4.jar" manifest="jars/dep-on-relvertest-3-4.mf"/>
153
        <jar jarfile="jars/dep-on-relvertest-some.jar" manifest="jars/dep-on-relvertest-some.mf"/>
153
        <jar jarfile="jars/dep-on-relvertest-some.jar" manifest="jars/dep-on-relvertest-some.mf"/>
154
        <jar jarfile="jars/depends-on-simple-module-2.jar" manifest="jars/depends-on-simple-module-2.mf"/>
154
        <jar jarfile="jars/depends-on-simple-module-2.jar" manifest="jars/depends-on-simple-module-2.mf"/>
155
        <jar jarfile="jars/needs-foo.jar" manifest="jars/needs-foo.mf"/>
156
        <jar jarfile="jars/prov-foo-depends-needs_foo.jar" manifest="jars/prov-foo-depends-needs_foo.mf"/>
155
        <antcall target="create-jar">
157
        <antcall target="create-jar">
156
            <param name="name" value="api-mod-export-all"/>
158
            <param name="name" value="api-mod-export-all"/>
157
            <param name="sourcedir" value="jars/exposes-api"/>
159
            <param name="sourcedir" value="jars/exposes-api"/>
(-)core/startup/test/unit/src/org/netbeans/core/startup/jars/needs-foo.mf (+4 lines)
Added Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: needs_foo
3
OpenIDE-Module-Name: Needs foo
4
OpenIDE-Module-Needs: foo
(-)core/startup/test/unit/src/org/netbeans/core/startup/jars/prov-foo-depends-needs_foo.mf (+5 lines)
Added Link Here
1
Manifest-Version: 1.0
2
OpenIDE-Module: prov_foo
3
OpenIDE-Module-Name: Provides foo a Depends on Needs_Foo
4
OpenIDE-Module-Provides: foo
5
OpenIDE-Module-Module-Dependencies: needs_foo

Return to bug 34699