2014-01-22 2 views
2

Я работаю над тем, чтобы Gradle генерировал определение артефакта IntelliJ WAR как часть задачи «идея» в соответствии с this blog post. До сих пор это работало довольно успешно, хотя мой код довольно грязный, поэтому я пытаюсь его очистить. Насколько мне известно, военная задача должна содержать всю информацию, необходимую для создания необходимых тегов в IntelliJ. Например, если объект Gradle проекта, скажем gradleProject, я могу сделать что-то вроде:Плагин Gradle WAR: как найти место для копирования файлов

def artifactManager = project.component.find { [email protected] == 'ArtifactManager' } as Node 
if (artifactManager) { 
    Node artifact = artifactManager.artifact.find { [email protected] == '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 

изменить или создать свой IntelliJ .ipr файл. Теперь я добавил некоторые файлы в моей WAR артефакта в сценарии Gradle как в:

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') 
    } 
} 

, и я хотел бы добавить некоторые Groovy код, чтобы забрать эти файлы и создать правильные теги XML, чтобы иметь IntelliJ копию их в правильных местах. Каков самый простой способ сделать это? Я пытался играть со следующим:

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

но список исходных файлов включает в себя все файлы, независимо от их назначения (все, LIBS web.xml, классы и т.д.).

Как я могу достичь того, что я пытаюсь сделать?

ответ

1

Я, наконец, понял это с помощью документов Gradle и небольшой проб и ошибок. Я получил желаемый результат, используя следующий код:

def artifactManager = project.component.find { [email protected] == 'ArtifactManager' } as Node 
if (artifactManager) { 
    Node artifact = artifactManager.artifact.find { [email protected] == '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') { 
    println "Adding files to root" 
    gradleProject.war.rootSpec.children.each { 
     if (it.destPath.pathString.equals("")) { 
     add(builder, it, "") 
     } 
    } 
    println "Adding files to META-INF" 
    element(id: 'directory', name: 'META-INF') { 
     gradleProject.war.rootSpec.children.each { 
     if (it.destPath.pathString.equals("META-INF")) { 
      add(builder, it, "META-INF") 
     } 
     } 
    } 
    println "Adding files to WEB-INF" 
    element(id: 'directory', name: 'WEB-INF') { 
     element(id: 'file-copy', path: gradleProject.war.webXml) 
     gradleProject.war.rootSpec.children.each { 
     if (it.destPath.pathString.equals("WEB-INF")) { 
      add(builder, it, "WEB-INF") 
     } 
     } 
     Set<String> excludeJars = [] as Set 
     element(id: 'directory', name: 'classes') { 
     element(id: 'module-output', name: gradleProject.name) 
     gradleProject.configurations.runtime.allDependencies.each { 
      if (it.hasProperty('dependencyProject')) { 
      if (it.dependencyProject.hasProperty('jar')) 
       excludeJars.add(it.dependencyProject.jar.archiveName) 
      element(id: 'module-output', name: it.dependencyProject.name) 
      } 
     } 
     } 
     element(id: 'directory', name: 'lib') { 
     gradleProject.configurations.runtime.each { 
      if (!excludeJars.contains(it.name)) 
      element(id: 'file-copy', path: it) 
     } 
     } 
    } 
    } 
} 
artifactManager.append artifact 

с функцией add определяется как:

def add(NodeBuilder builder, Object s, String dest, String prefix = "") { 
    println(prefix + "current destination: [" + dest + "]") 
    if (s instanceof File) { 
    println(prefix + "-- file " + s.toString()) 
    builder.element(id: 'file-copy', path: s) 
    } else if (s instanceof FileTree) { 
    println(prefix + "-- folder " + s.dir.toString()) 
    builder.element(id: 'dir-copy', path: s.dir) 
    } else if (s instanceof CopySpecInternal) { 
    print(prefix + "-- copy spec " + s.toString() + " with destination path: [" + s.destPath.pathString + "]; ") 
    if (dest.equals(s.destPath.pathString)) { 
     println("destination matches current folder") 
     s.sourcePaths.each { path -> 
      add(builder, path, dest, prefix + " ") 
     } 
     s.children.each { child -> add(builder, child, dest, prefix + " ") } 
    } else { 
     println("") 
     if (s.destPath.segments != null && s.destPath.segments.length > 0 && s.destPath.segments[0].equals(dest)) { 
     String relDest = new RelativePath(false, Arrays.copyOfRange(s.destPath.segments, 1, s.destPath.segments.length)).pathString 
     builder.element(id: 'directory', name: relDest) { 
      s.sourcePaths.each { path -> 
      add(builder, path, relDest, prefix + " ") 
      } 
      s.children.each { child -> add(builder, child, relDest, prefix + " ") } 
     } 
     } else { 
     println(prefix + "!! destination path is not relative to [" + dest + "]: [" + s.destPath.pathString + "]") 
     } 
    } 
    } else println(prefix + "?? unknown " + s.toString()) 
} 

Я в основном декомпиляции в war свойств задачи и впился в дерево файлов для копирования. Насколько я могу судить, эта задача не предоставляет интерфейс для такого рода вещей, поэтому мне пришлось прибегнуть к «хакерскому» решению, которое не является моим любимым. Я был бы рад, если бы кто-нибудь смог пообщаться с более чистым кодом.

Смежные вопросы