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 53898
Collapse All | Expand All

(-)a/core.startup/src/org/netbeans/core/startup/ModuleList.java (-1 / +7 lines)
Lines 1616-1621 final class ModuleList implements Stamps Link Here
1616
                    if (! cnb.equals(props.get("name"))) throw new IOException("Code name mismatch"); // NOI18N
1616
                    if (! cnb.equals(props.get("name"))) throw new IOException("Code name mismatch"); // NOI18N
1617
                    String jar = (String)props.get("jar"); // NOI18N
1617
                    String jar = (String)props.get("jar"); // NOI18N
1618
                    File jarFile = findJarByName(jar, cnb);
1618
                    File jarFile = findJarByName(jar, cnb);
1619
                    String manifest = (String)props.get("manifest"); // NOI18N
1620
                    File manifestFile = manifest == null ? null : findJarByName(manifest, cnb);
1619
                    Boolean reloadableB = (Boolean)props.get("reloadable"); // NOI18N
1621
                    Boolean reloadableB = (Boolean)props.get("reloadable"); // NOI18N
1620
                    boolean reloadable = (reloadableB != null ? reloadableB.booleanValue() : false);
1622
                    boolean reloadable = (reloadableB != null ? reloadableB.booleanValue() : false);
1621
                    Boolean autoloadB = (Boolean)props.get("autoload"); // NOI18N
1623
                    Boolean autoloadB = (Boolean)props.get("autoload"); // NOI18N
Lines 1624-1630 final class ModuleList implements Stamps Link Here
1624
                    boolean eager = (eagerB != null ? eagerB.booleanValue() : false);
1626
                    boolean eager = (eagerB != null ? eagerB.booleanValue() : false);
1625
                    Module m;
1627
                    Module m;
1626
                    try {
1628
                    try {
1627
                        m = mgr.create(jarFile, new ModuleHistory(jar), reloadable, autoload, eager);
1629
                        if (manifestFile != null) {
1630
                            m = mgr.create(manifestFile, jarFile, new ModuleHistory(jar), reloadable, autoload, eager);
1631
                        } else {
1632
                            m = mgr.create(jarFile, new ModuleHistory(jar), reloadable, autoload, eager);
1633
                        }
1628
                    } catch (DuplicateException dupe) {
1634
                    } catch (DuplicateException dupe) {
1629
                        // XXX should this be tolerated somehow? In case the original is
1635
                        // XXX should this be tolerated somehow? In case the original is
1630
                        // in fact scheduled for deletion anyway?
1636
                        // in fact scheduled for deletion anyway?
(-)a/core.startup/test/unit/src/org/netbeans/core/startup/ModuleListTest.java (+67 lines)
Lines 281-285 public class ModuleListTest extends Setu Link Here
281
    // to install and remove the Modules/ entries in a MFS
281
    // to install and remove the Modules/ entries in a MFS
282
    // and check that layer-driven events are enough to cause
282
    // and check that layer-driven events are enough to cause
283
    // complex installations & uninstallations
283
    // complex installations & uninstallations
284
285
    public void testAddNewModuleExternalViaXML() throws Exception {
286
        mgr.mutexPrivileged().enterWriteAccess();
287
        try {
288
            assertEquals(Collections.emptySet(), list.readInitial());
289
            assertEquals(Collections.emptySet(), mgr.getModules());
290
            list.trigger(Collections.<Module>emptySet());
291
            assertEquals(Collections.emptySet(), mgr.getModules());
292
        } finally {
293
            mgr.mutexPrivileged().exitWriteAccess();
294
        }
295
        LoggedPCListener listener = new LoggedPCListener();
296
        mgr.addPropertyChangeListener(listener);
297
        modulesfolder.getFileSystem().runAtomicAction(new FileSystem.AtomicAction() {
298
            public void run() throws IOException {
299
                // XXX this will require that there be an appropriate InstalledFileLocator in Lookup
300
                FileObject fooxml = modulesfolder.createData("org-foo", "xml");
301
                copy(new File(JARS, "org-foo.xml"), fooxml);
302
303
                FileObject barxml = modulesfolder.createData("org-bar", "xml");
304
                File mf2 = new File(JARS, "depends-on-simple-module.mf");
305
                String xml = 
306
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
307
"<!DOCTYPE module PUBLIC \"-//NetBeans//DTD Module Status 1.0//EN\"\n" +
308
"                        \"http://www.netbeans.org/dtds/module-status-1_0.dtd\">\n" +
309
"<module name=\"org.bar\">\n" +
310
"    <param name=\"autoload\">false</param>\n" +
311
"    <param name=\"eager\">false</param>\n" +
312
"    <param name=\"enabled\">true</param>\n" +
313
"    <param name=\"jar\">" + new File(JARS, "depends-on-simple-module-external.jar") + "</param>\n" +
314
"    <param name=\"manifest\">" + mf2 + "</param>\n" +
315
"    <param name=\"release\">1</param>\n" +
316
"    <param name=\"reloadable\">false</param>\n" +
317
"</module>\n";
318
                OutputStream os = barxml.getOutputStream();
319
                os.write(xml.getBytes("UTF-8"));
320
                os.close();
321
            }
322
        });
323
        assertTrue("PROP_MODULES fired", listener.waitForChange(mgr, ModuleManager.PROP_MODULES));
324
        mgr.mutexPrivileged().enterReadAccess();
325
        try {
326
            Set modules = mgr.getEnabledModules();
327
            assertEquals(2, modules.size());
328
            TreeSet<String> names = new TreeSet<String>();
329
            {
330
                Iterator it  = modules.iterator();
331
                Module m = (Module)it.next();
332
                names.add(m.getCodeNameBase());
333
                assertTrue(m.isEnabled());
334
                m = (Module)it.next();
335
                assertTrue(m.isEnabled());
336
                names.add(m.getCodeNameBase());
337
            }
338
            
339
            Iterator<String> it = names.iterator();
340
            assertEquals("org.bar", it.next());
341
            assertEquals("org.foo", it.next());
342
            
343
            Class<?> clazz = mgr.getClassLoader().loadClass("org.bar.SomethingElse");
344
            Class<?> supr = clazz.getSuperclass();
345
            assertEquals("Parent is loaded from other module", "org.foo.Something", supr.getName());
346
            
347
        } finally {
348
            mgr.mutexPrivileged().exitReadAccess();
349
        }
350
    }
284
    
351
    
285
}
352
}
(-)a/core.startup/test/unit/src/org/netbeans/core/startup/ModuleManagerTest.java (+94 lines)
Lines 140-145 public class ModuleManagerTest extends S Link Here
140
        mgr.mutexPrivileged().enterWriteAccess();
140
        mgr.mutexPrivileged().enterWriteAccess();
141
        try {
141
        try {
142
            Module m2 = mgr.create(new File(jars, "depends-on-simple-module.jar"), null, false, false, false);
142
            Module m2 = mgr.create(new File(jars, "depends-on-simple-module.jar"), null, false, false, false);
143
            Module m1 = mgr.create(new File(jars, "simple-module.jar"), null, false, false, false);
144
            assertEquals("org.foo", m1.getCodeNameBase());
145
            assertEquals("org.bar", m2.getCodeNameBase());
146
            assertEquals(Collections.EMPTY_SET, m1.getDependencies());
147
            assertEquals(Dependency.create(Dependency.TYPE_MODULE, "org.foo/1"), m2.getDependencies());
148
            Map<String,Module> modulesByName = new HashMap<String,Module>();
149
            modulesByName.put(m1.getCodeNameBase(), m1);
150
            modulesByName.put(m2.getCodeNameBase(), m2);
151
            List<Module> m1m2 = Arrays.asList(m1, m2);
152
            List<Module> m2m1 = Arrays.asList(m2, m1);
153
            Map<Module,List<Module>> deps = Util.moduleDependencies(m1m2, modulesByName, Collections.<String,Set<Module>>emptyMap());
154
            assertNull(deps.get(m1));
155
            assertEquals(Collections.singletonList(m1), deps.get(m2));
156
            assertEquals(m2m1, Utilities.topologicalSort(m1m2, deps));
157
            assertEquals(m2m1, Utilities.topologicalSort(m2m1, deps));
158
            // Leave commented out since it has a (hopefully clean) mutation effect
159
            // and could affect results:
160
            /*
161
            assertEquals(Collections.EMPTY_SET, m1.getProblems());
162
            assertEquals(Collections.EMPTY_SET, m2.getProblems());
163
             */
164
            Set<Module> m1PlusM2 = new HashSet<Module>();
165
            m1PlusM2.add(m1);
166
            m1PlusM2.add(m2);
167
            List<Module> toEnable = mgr.simulateEnable(m1PlusM2);
168
            assertEquals("correct result of simulateEnable", Arrays.asList(m1, m2), toEnable);
169
            mgr.enable(m1PlusM2);
170
            assertEquals(Arrays.asList(
171
                "prepare",
172
                "prepare",
173
                "load"
174
            ), installer.actions);
175
            assertEquals(Arrays.asList(
176
                m1,
177
                m2,
178
                Arrays.asList(m1, m2)
179
            ), installer.args);
180
            Class somethingelse = Class.forName("org.bar.SomethingElse", true, m2.getClassLoader());
181
            Method somemethod = somethingelse.getMethod("message");
182
            assertEquals("hello", somemethod.invoke(somethingelse.newInstance()));
183
            installer.clear();
184
            List<Module> toDisable = mgr.simulateDisable(Collections.singleton(m1));
185
            assertEquals("correct result of simulateDisable", Arrays.asList(m2, m1), toDisable);
186
            toDisable = mgr.simulateDisable(m1PlusM2);
187
            assertEquals("correct result of simulateDisable #2", Arrays.asList(m2, m1), toDisable);
188
            mgr.disable(m1PlusM2);
189
            assertFalse(m1.isEnabled());
190
            assertFalse(m2.isEnabled());
191
            assertEquals(Collections.EMPTY_SET, mgr.getEnabledModules());
192
            assertEquals(m1PlusM2, mgr.getModules());
193
            assertEquals(Arrays.asList(
194
                "unload",
195
                "dispose",
196
                "dispose"
197
            ), installer.actions);
198
            assertEquals(Arrays.asList(
199
                Arrays.asList(m2, m1),
200
                m2,
201
                m1
202
            ), installer.args);
203
            installer.clear();
204
            mgr.enable(m1);
205
            mgr.shutDown();
206
            assertEquals(Arrays.asList(
207
                "prepare",
208
                "load",
209
                "closing",
210
                "close"
211
            ), installer.actions);
212
            assertEquals(Arrays.asList(
213
                m1,
214
                Collections.singletonList(m1),
215
                Collections.singletonList(m1),
216
                Collections.singletonList(m1)
217
            ), installer.args);
218
        } finally {
219
            mgr.mutexPrivileged().exitWriteAccess();
220
        }
221
    }
222
    
223
    /** Load simple-module and depends-on-simple-module.
224
     * Make sure they can be installed and in a sane order.
225
     * Make sure a class from one can depend on a class from another.
226
     * Try to disable them too.
227
     */
228
    public void testSimpleInstallationOfExternalModule() throws Exception {
229
        FakeModuleInstaller installer = new FakeModuleInstaller();
230
        FakeEvents ev = new FakeEvents();
231
        ModuleManager mgr = new ModuleManager(installer, ev);
232
        mgr.mutexPrivileged().enterWriteAccess();
233
        try {
234
            File mf2 = new File(jars, "depends-on-simple-module.mf");
235
            assertTrue("mf2", mf2.exists());
236
            Module m2 = mgr.create(mf2, new File(jars, "depends-on-simple-module-external.jar"), null, false, false, false);
143
            Module m1 = mgr.create(new File(jars, "simple-module.jar"), null, false, false, false);
237
            Module m1 = mgr.create(new File(jars, "simple-module.jar"), null, false, false, false);
144
            assertEquals("org.foo", m1.getCodeNameBase());
238
            assertEquals("org.foo", m1.getCodeNameBase());
145
            assertEquals("org.bar", m2.getCodeNameBase());
239
            assertEquals("org.bar", m2.getCodeNameBase());
(-)a/core.startup/test/unit/src/org/netbeans/core/startup/build.xml (+6 lines)
Lines 62-67 made subject to such option by the copyr Link Here
62
            <param name="name" value="dep-on-dep-on-simple"/>
62
            <param name="name" value="dep-on-dep-on-simple"/>
63
            <param name="cp" value="${jars}/simple-module.jar:${jars}/depends-on-simple-module.jar"/>
63
            <param name="cp" value="${jars}/simple-module.jar:${jars}/depends-on-simple-module.jar"/>
64
        </antcall>
64
        </antcall>
65
        <jar manifest="jars/simple-module.mf" compress="false" jarfile="jars/depends-on-simple-module-external.jar">
66
            <fileset dir="jars/depends-on-simple-module">
67
                <exclude name="**/*.java"/>
68
                <exclude name="**/*.nbattrs"/>
69
            </fileset>
70
        </jar>
65
        <!-- For cyclic stuff, we precompile them together. For other tests -->
71
        <!-- For cyclic stuff, we precompile them together. For other tests -->
66
        <!-- this is illegal and we do not need to. -->
72
        <!-- this is illegal and we do not need to. -->
67
        <javac source="1.4" destdir="jars/cyclic-1">
73
        <javac source="1.4" destdir="jars/cyclic-1">
(-)a/o.n.bootstrap/manifest.mf (-1 / +1 lines)
Lines 1-4 Manifest-Version: 1.0 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.bootstrap/1
2
OpenIDE-Module: org.netbeans.bootstrap/1
3
OpenIDE-Module-Specification-Version: 2.13
3
OpenIDE-Module-Specification-Version: 2.14
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/netbeans/Bundle.properties
(-)a/o.n.bootstrap/src/org/netbeans/ModuleFactory.java (+12 lines)
Lines 64-69 public class ModuleFactory { Link Here
64
            throws IOException {
64
            throws IOException {
65
        return new StandardModule(mgr, ev, jar, history, reloadable, autoload, eager);
65
        return new StandardModule(mgr, ev, jar, history, reloadable, autoload, eager);
66
    }
66
    }
67
    
68
    
69
    /**
70
     * This method creates a "standard" module with external manifest.
71
     * @see StandardModule
72
     * @since 2.14
73
     */
74
    public Module create(File manifest, File jar, Object history, boolean reloadable,
75
            boolean autoload, boolean eager, ModuleManager mgr, Events ev)
76
            throws IOException {
77
        return new StandardModule(mgr, ev, manifest, jar, history, reloadable, autoload, eager);
78
    }
67
79
68
    /**
80
    /**
69
     * This method creates a "fixed" module. Fixed modules cannot be
81
     * This method creates a "fixed" module. Fixed modules cannot be
(-)a/o.n.bootstrap/src/org/netbeans/ModuleManager.java (-1 / +30 lines)
Lines 505-514 public final class ModuleManager { Link Here
505
     * You cannot request that a module be both autoload and eager.
505
     * You cannot request that a module be both autoload and eager.
506
     */
506
     */
507
    public Module create(File jar, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException, DuplicateException {
507
    public Module create(File jar, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException, DuplicateException {
508
        return create(null, jar, history, reloadable, autoload, eager);
509
    }
510
    
511
    /** Create a module from a JAR and external manifest add it to the managed set.
512
     * Will initially be disabled, unless it is eager and can
513
     * be enabled immediately.
514
     * May throw an IOException if the JAR file cannot be opened
515
     * for some reason, or is malformed.
516
     * If there is already a module of the same name managed,
517
     * throws a duplicate exception. In this case you may wish
518
     * to delete the original and try again.
519
     * You must give it some history object which can be used
520
     * to provide context for where the module came from and
521
     * whether it has been here before.
522
     * You cannot request that a module be both autoload and eager.
523
     * 
524
     * @since 2.14
525
     */
526
    public Module create(File manifest, File jar, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException, DuplicateException {
508
        assertWritable();
527
        assertWritable();
509
        ev.log(Events.START_CREATE_REGULAR_MODULE, jar);
528
        ev.log(Events.START_CREATE_REGULAR_MODULE, jar);
510
        Module m = moduleFactory.create(jar.getAbsoluteFile(),
529
        Module m;
530
        
531
        if (manifest == null) {
532
            m = moduleFactory.create(jar.getAbsoluteFile(),
511
                        history, reloadable, autoload, eager, this, ev);
533
                        history, reloadable, autoload, eager, this, ev);
534
        } else {
535
            m = moduleFactory.create(
536
                manifest, jar.getAbsoluteFile(), 
537
                history, reloadable, autoload, eager, 
538
                this, ev
539
            );
540
        }
512
        ev.log(Events.FINISH_CREATE_REGULAR_MODULE, jar);
541
        ev.log(Events.FINISH_CREATE_REGULAR_MODULE, jar);
513
        subCreate(m);
542
        subCreate(m);
514
        if (m.isEager()) {
543
        if (m.isEager()) {
(-)a/o.n.bootstrap/src/org/netbeans/StandardModule.java (+21 lines)
Lines 47-52 package org.netbeans; Link Here
47
// (NbBundle.getLocalizedValue is OK here.)
47
// (NbBundle.getLocalizedValue is OK here.)
48
48
49
import java.io.File;
49
import java.io.File;
50
import java.io.FileInputStream;
50
import java.io.IOException;
51
import java.io.IOException;
51
import java.io.InputStream;
52
import java.io.InputStream;
52
import java.security.AllPermission;
53
import java.security.AllPermission;
Lines 139-144 final class StandardModule extends Modul Link Here
139
        }
140
        }
140
        moduleJARs.add(jar);
141
        moduleJARs.add(jar);
141
    }
142
    }
143
    
144
    /** External module with manifest */
145
    StandardModule(ModuleManager mgr, Events ev, File manifest, File jar, Object history, boolean reloadable, boolean autoload, boolean eager) throws IOException {
146
        super(mgr, ev, history, reloadable, autoload, eager);
147
        this.jar = jar;
148
        FileInputStream is = new FileInputStream(manifest);
149
        this.manifest = new Manifest(is);
150
        is.close();
151
        parseManifest();
152
        findExtensionsAndVariants(this.manifest);
153
        // Check if some other module already listed this one in Class-Path.
154
        // For the chronologically reverse case, see findExtensionsAndVariants().
155
        Set<File> bogoOwners = extensionOwners.get(jar);
156
        if (bogoOwners != null) {
157
            Util.err.warning("module " + jar + " was incorrectly placed in the Class-Path of other JARs " + bogoOwners + "; please use OpenIDE-Module-Module-Dependencies instead");
158
        }
159
        moduleJARs.add(jar);
160
    }
161
    
162
    
142
163
143
    public @Override Manifest getManifest() {
164
    public @Override Manifest getManifest() {
144
        if (manifest == null) {
165
        if (manifest == null) {

Return to bug 53898