ProjectClassPathModifier and ProjectClassPathExtender

97 Views Asked by At

I am trying to contribute a fix to a Netbeans 8 plugin which is currently broken. The plugin includes an "add support" menu item which is supposed to, amongst other things, add an entry to the project class path if the project is an ANT project. Currently it does this by manually rewriting the project properties file. This fails in certain cases, e.g. if the project has a dedicated library folder. I have managed to code a fix which uses the ProjectClassExtender API class to add the library to the class, but this is a deprecated API. I've tried a couple of approaches to working via the replacement ProjectClassPathModifier, but I cannot get the right combination of parameters - I always get an Unsupported Operation exception or similar. Can someone please help here? The code below condenses the three approaches I've tried:

        FileObject projectRoot = project.getProjectDirectory();
        Sources sources = ProjectUtils.getSources(project);
        SourceGroup sourceGroup = sources.getSourceGroups(Sources.TYPE_GENERIC)[0];
        FileObject sgRoot = sourceGroup.getRootFolder();
        Library lib = libraryManager.getLibrary(LIB_NAME);
        ProjectClassPathModifier pcpm = projectLookup.lookup(ProjectClassPathModifier.class);
        ProjectClassPathExtender pcpe = pcpm.extenderForModifier(project);
        pcpe.addLibrary(lib); // Works but deprecated
        pcpm.addLibraries(new Library[]{lib}, projectRoot, ClassPath.COMPILE); // Fails regardless
        pcpm.addLibraries(new Library[]{lib}, sgRoot, ClassPath.COMPILE); // Fails regardless

The call using projectRoot gives this error:

Java.lang.UnsupportedOperationException: Project in C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication16 of class org.netbeans.modules.java.j2seproject.J2SEProject has a ProjectClassPathModifierImplementation but it will not handle classpath/compile for C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication16 extensible source groups: C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication16\src
at org.netbeans.api.java.project.classpath.ProjectClassPathModifier.findExtensible(ProjectClassPathModifier.java:388)
at org.netbeans.api.java.project.classpath.ProjectClassPathModifier.addLibraries(ProjectClassPathModifier.java:93)
at org.nemesis.antlr.v4.netbeans.v8.project.AntBasedProject.addPropertiesToProject(AntBasedProject.java:615)
at org.nemesis.antlr.v4.netbeans.v8.project.AntBasedProject.addANTLRSupport(AntBasedProject.java:122)
at org.nemesis.antlr.v4.netbeans.v8.project.action.AddANTLRSupport.actionPerformed(AddANTLRSupport.java:134)
[catch] at org.openide.awt.InjectorExactlyOne.actionPerformed(InjectorExactlyOne.java:78)
    at org.openide.awt.ContextAction$Performer.actionPerformed(ContextAction.java:226)
    at org.openide.awt.ContextManager.actionPerformed(ContextManager.java:260)
    at org.openide.awt.ContextAction.actionPerformed(ContextAction.java:109)
    at org.openide.util.actions.ActionInvoker$1.run(ActionInvoker.java:93)
    at org.openide.util.actions.ActionInvoker.doPerformAction(ActionInvoker.java:116)
    at org.openide.util.actions.ActionInvoker.invokeAction(ActionInvoker.java:99)
    at org.openide.awt.GeneralAction$BaseDelAction.actionPerformed(GeneralAction.java:234)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:842)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:886)
    at java.awt.Component.processMouseEvent(Component.java:6539)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
    at java.awt.Container.dispatchEventImpl(Container.java:2283)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue$4.run(EventQueue.java:733)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)

The call using sgRoot gives this very similar error:

java.lang.UnsupportedOperationException: Project in C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication17 of class org.netbeans.modules.java.j2seproject.J2SEProject has a ProjectClassPathModifierImplementation but it will not handle classpath/compile for C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication17 extensible source groups: C:\Users\sparry\ownCloud\development\NetbeansProjects\JavaApplication17\src
at org.netbeans.api.java.project.classpath.ProjectClassPathModifier.findExtensible(ProjectClassPathModifier.java:388)
at org.netbeans.api.java.project.classpath.ProjectClassPathModifier.addLibraries(ProjectClassPathModifier.java:93)
at org.nemesis.antlr.v4.netbeans.v8.project.AntBasedProject.addPropertiesToProject(AntBasedProject.java:616)
at org.nemesis.antlr.v4.netbeans.v8.project.AntBasedProject.addANTLRSupport(AntBasedProject.java:122)
at org.nemesis.antlr.v4.netbeans.v8.project.action.AddANTLRSupport.actionPerformed(AddANTLRSupport.java:134)
[catch] at org.openide.awt.InjectorExactlyOne.actionPerformed(InjectorExactlyOne.java:78)
    at org.openide.awt.ContextAction$Performer.actionPerformed(ContextAction.java:226)
    at org.openide.awt.ContextManager.actionPerformed(ContextManager.java:260)
    at org.openide.awt.ContextAction.actionPerformed(ContextAction.java:109)
    at org.openide.util.actions.ActionInvoker$1.run(ActionInvoker.java:93)
    at org.openide.util.actions.ActionInvoker.doPerformAction(ActionInvoker.java:116)
    at org.openide.util.actions.ActionInvoker.invokeAction(ActionInvoker.java:99)
    at org.openide.awt.GeneralAction$BaseDelAction.actionPerformed(GeneralAction.java:234)
    at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
    at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
    at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
    at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
    at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
    at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:842)
    at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:886)
    at java.awt.Component.processMouseEvent(Component.java:6539)
    at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
    at java.awt.Component.processEvent(Component.java:6304)
    at java.awt.Container.processEvent(Container.java:2239)
    at java.awt.Component.dispatchEventImpl(Component.java:4889)
    at java.awt.Container.dispatchEventImpl(Container.java:2297)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4904)
    at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4535)
    at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4476)
    at java.awt.Container.dispatchEventImpl(Container.java:2283)
    at java.awt.Window.dispatchEventImpl(Window.java:2746)
    at java.awt.Component.dispatchEvent(Component.java:4711)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:760)
    at java.awt.EventQueue.access$500(EventQueue.java:97)
    at java.awt.EventQueue$3.run(EventQueue.java:709)
    at java.awt.EventQueue$3.run(EventQueue.java:703)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:84)
    at java.awt.EventQueue$4.run(EventQueue.java:733)
    at java.awt.EventQueue$4.run(EventQueue.java:731)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:74)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:730)
    at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
1

There are 1 best solutions below

0
On

I think I have worked out the problem and a solution myself:

        Sources sources = ProjectUtils.getSources(project);
        SourceGroup sourceGroup = sources.getSourceGroups(JavaProjectConstants.SOURCES_TYPE_JAVA)[0];
        FileObject sgRoot = sourceGroup.getRootFolder();
        Library lib = libraryManager.getLibrary(LIB_NAME);
        ProjectClassPathModifier pcpm = projectLookup.lookup(ProjectClassPathModifier.class);
        pcpm.addLibraries(new Library[]{lib}, sgRoot, ClassPath.COMPILE); // works!

The key is using the JavaProjectConstants.SOURCES_TYPE_JAVA source type, not Sources.TYPE_GENERIC. Generic returns the project main folder and the addLibraries call needs a java source folder. In most projects, that's the src folder.