2013-04-08 26 views
0

我正在嘗試使用Gradle構建幾個罐子,而不是維護一個包含EJB的類的列表,以便我可以單獨部署它們我認爲在製作時可能很整潔地掃描類罐子裏。發佈工件覆蓋Gradle中的其他工件

與其加載類並使用反射來獲取註釋我認爲使用asm掃描類可能會更簡單,因此在其中一個任務中使用Chuncky ClassReader。

我不認爲這是問題所以可以忽略,基本上我有2個任務,我用它來定義罐子的內容,都報告說,不同的內容是通過eachFile打印出來進入他們,但是當我查看發佈存儲庫位置時,這兩個文件和關聯的sha1都是相同的。

Gradle壞了,或者更可能是我做了一些瘋狂的事,但看不到它是什麼,任何人都可以幫忙?

順便說一下,如果我禁用任何jar文件的發佈,那麼得到創建的是正確的,所以我認爲這是發佈的錯誤,而不是震驚,但可能是錯誤的。

// ASM is used to interpret the class files, this avoids having to load all classes in the vm and use reflection 
import org.objectweb.asm.* 
task ejbJar(type: Jar) { 
    //outputs.upToDateWhen { false } 
    from "${project.buildDir}/classes/main" 
    eachFile { println "EJB server: ${name}" } 
    include getEjbClassFiles(project.buildDir) 
} 

task clientEjbJar(type: Jar) { 
    //outputs.upToDateWhen { false } 
    from "${project.buildDir}/classes/main/com/company/core/versioner" 
    eachFile { println "Client EJB ${name}" } 
    include '**/*' 
} 

artifacts {  
    archives clientEjbJar 
    archives ejbJar 
} 
String[] getEjbClassFiles(base) { 
    def includedFiles = [] 
    def baseDir = project.file("${base}/classes/main") 
    def parentPath = baseDir.toPath() 
    if (baseDir.isDirectory()) { 
    baseDir.eachFileRecurse(groovy.io.FileType.FILES) { file -> 
     if(file.name.endsWith('.class')) { 
     //get hold of annotations in there --- org.objectweb.asm.Opcodes.ASM4 
     def reader = new ClassReader(file.bytes).accept(
      new ClassVisitor(Opcodes.ASM4) { 
      public AnnotationVisitor visitAnnotation(String desc, boolean visible) { 
       if(desc.equals("Ljavax/ejb/Stateless;") || 
       desc.equals("Ljavax/ejb/Stateful;")) { 
       includedFiles += parentPath.relativize(file.toPath()) 
       } 
       return null //no interest in actually visiting the annotation values 
      } 
      }, 
      ClassReader.SKIP_DEBUG | ClassReader.EXPAND_FRAMES | ClassReader.SKIP_FRAMES | ClassReader.SKIP_CODE 
     ) 
     } 
    } 
    } 
    return includedFiles 
}  

publishing { 
    publications { 
    mypub(IvyPublication) { 
     artifact(ejbJar) { 
     name 'ejb' 
     } 
     artifact(clientEjbJar) { 
     name 'client-ejb' 
     } 
    } 
    } 
    repositories { 
    ivy { 
     name 'personal' 
     url "${ant['developer.repository']}/" 
     layout 'pattern', { 
     artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]" 
    ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]" 
     } 
    } 
    } 
} 

我做下破事成更簡單的形式,因爲我認爲這可能是一個搖籃錯誤。

的簡化形式爲:

apply plugin: 'java' 
apply plugin: 'ivy-publish' 

task bigJar(type: Jar) { 
    from "${rootDir}/src/main/resources" 
    include '**/*' 
} 

task smallJar(type: Jar) { 
    from "${rootDir}/src/main/resources/A/B" 
    include '**/*' 
} 

group 'ICantBeEmpty' 
artifacts { 
    archives bigJar 
    archives smallJar 
} 

publishing { 
    publications { 
    mypub(IvyPublication) { 
     artifact(bigJar) { name 'biggie' } 
     artifact(smallJar) { name 'smallie' } 
    } 
    repositories { 
    ivy { 
    name 'personal' 
    url "c:/temp/gradletest" 
    layout 'pattern', { 
     artifact "[organisation]/[module]/[artifact]/[revision]/[type]/[artifact]-[revision].[ext]" 
     ivy "[organisation]/[module]/[type]/[revision]/[type]/[type]-[revision].[ext]" 
    } 
     } 
    } 
    } 
} 

這導致2個文件在C:/temp/gradletest/ICantBeEmpty/report-bug/biggie/unspecified/biggie-unspecified.jar和c:/溫度/ gradletest/ICantBeEmpty/report-bug/smallie/unspecified/smallie-unspecified.jar 這兩個文件都是相同的,但我想我知道爲什麼會看到我以後的答案。

回答

1

雖然看着一些配置,我注意到一些奇怪的行爲,導致我解決了這個問題,這是一個Gradle錯誤。

在我建立我有一個臨時任務做

configurations.archives.artifacts.each { println it } 

這給了我5個不同的線路輸出,但它改變這種

configurations.archives.artifacts.each { println it.file } 

產生相同的文件名的5倍。

事實證明這與我的問題有關,儘管工件在那裏是獨立的實體,用於唯一標識它們的名稱是相同的,因此在發佈期間總是選擇相同的文件。工件的名稱默認在java插件中由$ {baseName} - $ {appendix} - $ {version} - $ {classifier}。$ {extension}給出。這意味着如果沒有指定附錄或分類器,那麼工件將具有相同的名稱。

我通過添加附件名稱

task bigJar(type: Jar) { 
    appendix = 'big' 
    from "${rootDir}/src/main/resources" 
    include '**/*' 
} 

task smallJar(type: Jar) { 
    appendix = 'small' 
    from "${rootDir}/src/main/resources/A/B" 
    include '**/*' 
} 

使用此而不是從問題的代碼產生2個不同的瓶測試此使用上述示例代碼。

0

這不是一個完整的答案,而是一個足夠好的解決辦法,如果我添加一個新的出版物的定義我可以發佈,我想給我想要的位置的工件,唯一的缺點是,它會創建另一個gradle這個這不是理想的任務。

publications { 
     mypub(IvyPublication) { 
     artifact(ejbJar) { 
      name 'ejb' 
     } 
     } 
     newpub(IvyPublication) { 
     artifact(clientEjbJar) { 
      name 'client-ejb' 
     } 
     } 
    } 
0

以上回答工作在短期內,但是沒有透露另一個短的搖籃世界未來enter link description here

不知道搖籃,是所有可能的時刻,至今沒有人回答我的問題,所以也許這不是積極開發的!

0

我不是Gradle的這一部分的專家,但您使用的功能標記爲「incubating」;您正在使用可能或可能不完整的新發布功能。也許你應該使用old way做事。您似乎也正在通過使用artifacts閉包來混合兩種方式。

+0

感謝您的興趣,但'舊的方式'鏈接顯示我正在做的事情,除了我正在使用常春藤回購而不是平面文件。因爲處於孵化狀態的東西並不意味着它不應該被使用,並且會引發問題,這是開源演化如此迅速的本質。我現在已經確定了這個問題,因爲用於在配置中定位工件的名稱不是唯一的,並且會發布完整的描述以保存其他Gradle用戶同樣的麻煩。 – 2013-05-08 10:42:44