| Summary: | NPE thrown from base class's equals() causes role creation to fail | ||
|---|---|---|---|
| Product: | [Tools] Objectteams | Reporter: | Stephan Herrmann <stephan.herrmann> |
| Component: | OTJ | Assignee: | Project Inbox <objectteams.otj-inbox> |
| Status: | NEW --- | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | ||
| Version: | 0.7 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Linux | ||
| Whiteboard: | |||
This was observed in OTEquinoxBuilderTests by the following stacktrace: java.lang.NullPointerException at org.eclipse.pde.internal.core.PDEClasspathContainer$Rule.equals(PDEClasspathContainer.java:31) at java.util.WeakHashMap.isEqual(WeakHashMap.java:737) at java.util.WeakHashMap.put(WeakHashMap.java:612) at org.objectteams.DoublyWeakHashMap.put(DoublyWeakHashMap.java:69) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor$__OT__Rule.<init>(PDEAdaptor.java:154) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor._OT$create$Rule(PDEAdaptor.java:153) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor.access$3(PDEAdaptor.java:152) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor$__OT__RequiredPluginsClasspathContainer.addForcedExports(PDEAdaptor.java:112) at org.eclipse.objectteams.otdt.internal.compiler.adaptor.PDEAdaptor._OT$RequiredPluginsClasspathContainer$addForcedExports$getInclusions(PDEAdaptor.java:94) at org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer._OT$getInclusions$chain(RequiredPluginsClasspathContainer.java) at org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer.getInclusions(RequiredPluginsClasspathContainer.java) at org.eclipse.pde.internal.core.RequiredPluginsClasspathContainer.getInclusions(RequiredPluginsClasspathContainer.java:272) Here is the code being executed: protected Rule(RequiredPluginsClasspathContainer encl, AdaptedBaseBundle aspectBindingData, String packageName) { encl.base(); // base constructor ... setPath(..); ... } Inspecting the code it tells us that role creation tried to insert the base-role pair into the role cache, which seemed to collide with an existing entry so DoublyWeakHashMap had to call equals(). However, at this point the base object (Rule) was not fully initialized and thus equals() threw NPE. This is ugly, because the role has no chance to fully initialize its base object before the map.put, because the constructor of Rule doesn't suffice for this initialization criterion, but setPath() must be called afterwards. One might argue that the design of the base class is bogus, but since we don't own that class, we must somehow cope with the situation. Ideas include: * catch NPE within the generated role registration code. but then what? * add syntax for telling the compiler that role registration should be deferred until after some more statements, like: encl.base() { setPath(..); }; // only now the base is fully initialized This is kindof funky syntax and we would have to add special rules for the initialization block: use callout only with great care etc. Notably: the base instance must not leak to locations that may cause it to be lifted (which isn't yet possible!).