Search code examples
eclipsegradlejava-11buildshipeclipse-classpath

Adding a module export to the Eclipse .classpath file


I have an older project which needs to have a module export in Eclipse's .classpath file, so that it can resolve some classes from this module. The classpath entry looks like this if I generate it via Eclipse's build path editor:

<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/">
    <attributes>
        <attribute name="module" value="true"/>
        <attribute name="add-exports" value="java.desktop/com.sun.java.swing.plaf.motif=ALL-UNNAMED"/>
    </attributes>
</classpathentry>

Naturally, I'd like to have that entry generated by Gradle and I have finally managed to do that:

eclipse.classpath.file {
    whenMerged {    // remove any JRE containers
        entries.findAll{ it.path ==~ '.*JRE_CONTAINER.*' }.each { entries.remove(it) }
    }
    withXml {       // add one with the required export
        def node = it.asNode()
        def cpe = new Node(node, 'classpathentry', [kind: 'con', path: 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11/'])
        def attrs = new Node(cpe, 'attributes')
        new Node(attrs, 'attribute', [name: 'module', value: 'true'])
        new Node(attrs, 'attribute', [name: 'add-exports', value: 'java.desktop/com.sun.java.swing.plaf.motif=ALL-UNNAMED'])
    }
}

But this seems crude and overly verbose. Is there a simpler way to do something like this?

Update: Also, this only works when running gradle eclipse, but not when doing a "Refresh Gradle Project" with Buildship - as that doesn't consider withXml. So I'd need to create a Container in whenMerged and add attributes to it, which I haven't been able to do.


Solution

  • I've found the solution, the attribute(s) nodes are accessible via the entryAttributes field of the AbstractClassEntry class.

    This way, I can just do...

    eclipse.classpath.file {
        whenMerged {
            entries.find{ it.path ==~ '.*JRE_CONTAINER.*' }.each { 
                it.entryAttributes['module'] = true
                it.entryAttributes['add-exports'] = 'java.desktop/com.sun.java.swing.plaf.motif=ALL-UNNAMED'
            }
        }
    }
    

    ...and it will be applied by Buildship, too.