Gradle WAR artifact in IntelliJ: the extra mile


(Giovanni Botta) #1

I’ve been working on having Gradle generate an IntelliJ WAR artifact definition as part of the ‘idea’ task as per this blog post. This has worked pretty successfully so far although my code is quite dirty so I’m trying to clean it up.

As far as I’m concerned, the war task should contain all the information required to create the necessary tags in the IntelliJ. For example, given a Gradle Project object, say gradleProject, I can do something like:

def artifactManager = project.component.find { it.@name == 'ArtifactManager' } as Node
if (artifactManager) {
  Node artifact = artifactManager.artifact.find { it.@type == 'exploded-war' }
  if (artifact) {
    artifactManager.remove(artifact)
  }
} else {
  artifactManager = project.appendNode('component', [name: 'ArtifactManager']);
}
def builder = new NodeBuilder();
def artifact = builder.artifact(type: 'exploded-war', name: "${gradleProject.name} exploded war") {
  'output-path'("${gradleProject.buildDir}/${gradleProject.name}-exploded.war")
  root(id: 'root') {
    element(id: 'directory', name: 'WEB-INF') {
      // copy web.xml
      element(id: 'file-copy', path: gradleProject.war.webXml)
      Set<String> excludeJars = [] as Set
      element(id: 'directory', name: 'classes') {
        // copy classes
        element(id: 'module-output', name: gradleProject.name)
        // copy depending projects module output (classes)
        gradleProject.configurations.runtime.allDependencies.each {
          if (it.hasProperty('dependencyProject')) { // TODO: make it functional?!?
            if (it.dependencyProject.hasProperty('jar'))
              excludeJars.add(it.dependencyProject.jar.archiveName)
            element(id: 'module-output', name: it.dependencyProject.name)
          }
        }
      }
      // copy dependency jars excluding possible existing module jars (not sure it's necessary)
      element(id: 'directory', name: 'lib') {
        // TODO: this should handle ALL kinds of dependencies
        gradleProject.configurations.runtime.each {
          if (!excludeJars.contains(it.name))
            element(id: 'file-copy', path: it)
        }
      }
    }
  }
}
artifactManager.append artifact

to modify or create my IntelliJ .ipr file. Now I have added some files to my WAR artifact in the Gradle script as in:

war{
  from project(':rest').file('resource/some.properties')
  from project(':some_project').fileTree('some_folder')
  metaInf {
    from parent.file('build/config/website/' + environment + '/context.xml')
  }
}

and I’d like to add some Groovy code to pick up those files and create the correct XML tags to have IntelliJ copy them in the right locations. What’s the simplest way to do this? I tried playing with the following:

gradleProject.war.source.each { // ... create tags etc.
}

but the list of source files includes all the files, regardless of their destination (all libs, web.xml, classes, etc.).

How can I achieve what I’m trying to do? Thanks