2011-02-24 81 views
1

我有一個使用jaxb2-maven-plugin來編譯一些xsd文件的Maven項目。它使用staleFile來確定是否有任何引用的schemaFiles已被更改。不幸的是,有問題的xsd文件使用<xs:include schemaLocation="../relative/path.xsd"/>標記來包含schemaFile參數中未列出的其他模式文件,因此插件中的staleFile計算不能準確檢測何時需要實際重新編譯。隨着包含的模式的發展,這將打破增量構建。如何遞歸地解析xsd文件以生成Maven中增量構建的包含模式列表?

很明顯,一種解決方案是列出執行的schemaFile中的所有遞歸引用文件。但是,有些情況下開發人員不會這樣做並破壞構建。我希望以某種方式自動生成此列表。

想到的一種方法是以某種方式解析頂級XSD文件,然後設置一個屬性或輸出一個文件,然後我可以將其傳遞到schemaFile參數或schemaFiles參數中。 Groovy gmaven插件似乎可能是將該功能嵌入到POM中的一種自然方式。但是我對Groovy開始並不熟悉。

任何人都可以提供一些示例代碼?或者提供一個替代實施/解決方案?

謝謝!

回答

1

的路徑列表,下面是一個可行的解決方案,你可能不得不根據你如何配置jaxb2插件來跺腳。

配置一個gmaven-plugin執行的生命週期(例如,在初始化階段)早期以下列配置運行...

開始用函數來收集參考架構的文件對象(這是一個細化Tim的答案):

def findRefs { f -> 
    def relPaths = new XmlSlurper().parse(f).depthFirst().findAll { 
     it.name()=='include' 
    }*[email protected]*.text() 
    relPaths.collect { new File(f.absoluteFile.parent + "/" + it).canonicalFile } 
} 

包裹在一個函數的結果,直到所有的孩子迭代中發現:

def recursiveFindRefs = { schemaFiles -> 
    def outputs = [] as Set 
    def inputs = schemaFiles as Queue 
    // Breadth-first examine all refs in all schema files 
    while (xsd = inputs.poll()) { 
     outputs << xsd 
     findRefs(xsd).each { 
      if (!outputs.contains(it)) inputs.add(it) 
     } 
    } 
    outputs 
} 

當你解析Maven項目來確定要做什麼時,真正的魔法就出現了。 首先,找到JAXB插件:

jaxb = project.build.plugins.find { it.artifactId == 'jaxb2-maven-plugin' } 

然後,解析插件每次執行(如果有多個)。該代碼假設每個執行設置爲schemaDirectory,schemaFilesstaleFile(即,不使用默認值!),並且不使用schemaListFileName

jaxb.executions.each { ex -> 
    log.info("Processing jaxb execution $ex") 
    // Extract the schema locations; the configuration is an Xpp3Dom 
    ex.configuration.children.each { conf -> 
     switch (conf.name) { 
      case "schemaDirectory": 
       schemaDirectory = conf.value 
       break 
      case "schemaFiles": 
       schemaFiles = conf.value.split(/,\s*/) 
       break 
      case "staleFile": 
       staleFile = conf.value 
       break 
     } 
    } 

最後,我們可以打開schemaFiles,用我們前面定義的函數解析這些:

def schemaHandles = schemaFiles.collect { new File("${project.basedir}/${schemaDirectory}", it) } 
    def allSchemaHandles = recursiveFindRefs(schemaHandles) 

...,並比較他們的最後修改與舊文件的修改時間相對應的時間, 根據需要取消舊文件的鏈接。

def maxLastModified = allSchemaHandles.collect { 
      it.lastModified() 
     }.max() 
    def staleHandle = new File(staleFile) 
    if (staleHandle.lastModified() < maxLastModified) { 
     log.info(" New schemas detected; unlinking $staleFile.") 
     staleHandle.delete() 
    } 
} 
1

不知道你會如何將其集成到你的Maven構建 - Maven是不是真的我的事:-(

但是,如果你有路徑的xsd文件,你應該能夠得到它通過執行類似引用文件:

def rootXsd = new File('path/to/xsd') 
def refs = new XmlSlurper().parse(rootXsd).depthFirst().findAll { it.name()=='include' }[email protected]*.text() 
println "$rootXsd references $refs" 

所以refs是字符串應該是基於tim_yates的回答所包含的XSD

+0

傳播點運算符是必需的,因爲'findAll'返回一個List:'*。@ schemaLocation'。無論如何,謝謝你的代碼片段,效果很好':)'+1! – albciff 2016-03-16 23:06:45

相關問題