import groovy.xml.MarkupBuilder import org.gradle.api.dependencies.ProjectDependency /* * This plugin class handles the generation of Eclipse project files and, in the case of a WebProject, WTP * files * * @author phil.messenger */ class EclipsePlugin implements org.gradle.api.Plugin { public void apply(org.gradle.api.Project currentProject, org.gradle.api.internal.project.PluginRegistry pluginRegistry, java.util.Map customValues) { def outputDirectory; try { outputDirectory = project.outputDirectory } catch(ex) { outputDirectory = 'build/classes' } currentProject.createTask('eclipse') { currentTask -> Closure eclipseClasspath = { project -> println "Generating eclipse classpath for ${project.name}" //get the dependency resolver bits def dr = project.dependencies.dependencyResolver def ivy = project.dependencies.ivy def mdc = project.dependencies.moduleDescriptorConverter //get the classpath entries, ignoring ones we can't resolve def classPathEntries = dr.resolve('runtime', ivy, mdc.convert(project.dependencies), false) File eclipseClasspathFile = project.file('.classpath') //if the eclipse classpath file doesn't exist, create an empty one if (!eclipseClasspathFile.exists()) { eclipseClasspathFile.append ('') } //make a backup of the existing eclipse project file project.ant.copy(file: eclipseClasspathFile, toFile: "${eclipseClasspathFile}.old", overwrite: true) //load it into memory as a DOM def classpathXml = new XmlParser().parseText(eclipseClasspathFile.text) //remove existing libs classpathXml.classpathentry.findAll{ it.'@kind'.equals('lib') }.each { e -> classpathXml.remove(e) } //add the libs into place classPathEntries.each { classpathXml.appendNode('classpathentry', [kind: 'lib', path: it.toString()]) } //source directories and output directories classpathXml.classpathentry.findAll{ it.'@kind'.equals('output') }.each { classpathXml.remove(it) } classpathXml.classpathentry.findAll{ it.'@kind'.equals('src') }.each { classpathXml.remove(it) } //main source def sourceClosure = {name -> classpathXml.appendNode('classpathentry', [kind: 'src', path: "${project.srcRootName}/${name}"])} project.srcDirNames.each { sourceClosure(it) } //resources that should be on the classpath project.resourceDirNames.each { if(project.file(it).exists()) {sourceClosure(it)} } //output for normal classes classpathXml.appendNode('classpathentry', [kind: 'output', path: outputDirectory]) //test source project.testSrcDirNames.each { name -> if(new File("${project.srcRootName}/${name}").exists()) { classpathXml.appendNode('classpathentry', [kind: 'src', path: "${project.srcRootName}/${name}", output: project.testOutputDirectory]) } } //add reference to default JRE/JDK if(classpathXml.classpathentry.findAll{ it.'@kind'.equals('con')}.size == 0) { classpathXml.appendNode('classpathentry', [kind: 'con', path: 'org.eclipse.jdt.launching.JRE_CONTAINER']) } //add reference to dependant projects as project references project.dependencies.dependencies.each { if(it instanceof ProjectDependency) { classpathXml.appendNode('classpathentry', [kind: 'src', path: "/${it.getDependencyProject().name}", combineaccessrules: 'false']) } } //write the new classpath file new XmlNodePrinter(new PrintWriter(project.file('.classpath'))).print(classpathXml) } Closure eclipseWTP = { project -> println "Generating eclipse WTP settings for ${project.name}" //get references to the dependency resolver def dr = project.dependencies.dependencyResolver def ivy = project.dependencies.ivy def mdc = project.dependencies.moduleDescriptorConverter //get the classpath entries, ignoring ones we can't resolve def classPathEntries = dr.resolve('runtime', ivy, mdc.convert(project.dependencies), false) File wtpFile = project.file('.settings/org.eclipse.wst.common.component'); if (wtpFile.exists()) { wtpFile.delete() } def xml = new MarkupBuilder(wtpFile.newWriter()) xml.'project-modules'(id: 'moduleCoreId', 'project-version': '1.5.0') { 'wb-module'('deploy-name': project.name) { property(name: 'context-root', value: project.name) 'wb-resource'('deploy-path': '/', 'source-path': 'src/main/webapp') 'wb-resource'('deploy-path': '/WEB-INF/classes', 'source-path': 'src/java') try { project.warResourceMappings.each { mapEntry -> 'wb-resource'('deploy-path' : "/${mapEntry.value}", 'source-path' : mapEntry.key) } } catch(ex) { println("No warResourceMappings specified; skipping") } property(name: 'java-output-path', value: "/${outputDirectory}") classPathEntries.each { 'dependent-module'('deploy-path': '/WEB-INF/lib', handle: "module:/classpath/lib/${it}") { 'dependency-type'('uses') } } project.dependencies.dependencies.each { if(it instanceof ProjectDependency) { 'dependent-module'('deploy-path': '/WEB-INF/lib', handle: "module:/resource/${it.getDependencyProject().name}/${it.getDependencyProject().name}") { 'dependency-type'('uses') } } } } } } //generate classpath for this project eclipseClasspath(currentProject) //generate classpath for any child projects if(currentProject.project.appliedPlugins.contains(org.gradle.api.plugins.WarPlugin.class)) { eclipseWTP(currentProject) } currentProject.childProjects.each { entry -> eclipseClasspath(entry.value) if(entry.value.appliedPlugins.contains(org.gradle.api.plugins.WarPlugin.class)) { eclipseWTP(entry.value) } } } } }