В моем последнем посте обсуждалось сравнение высокоуровневого содержимого двух JAR-файлов с использованием скрипта Groovy и поста 2011 года с отображением файла манифеста конкретного JAR-файла. Этот пост иллюстрирует сочетание этих двух идей с примером сравнения файлов манифеста двух разных файлов JAR.
Как показано в только что упомянутых двух сообщениях в блоге, с помощью Groovy легко манипулировать содержимым файла JAR. В то время как все эти манипуляции доступны в стандартном JDK и, следовательно, доступны для приложений Java, Groovy лучше подходит для таких сценариев, как этот. Groovy также предоставляет несколько удобных ярлыков синтаксиса. Мне нравится тот факт, что сценарий Groovy напоминает сценарий, а не объектно-ориентированный программный продукт.
Вот код для сравнения файлов Manifest.MF двух предоставленных файлов JAR:
manifestDiff.groovy
| 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | #!/usr/bin/env groovy/** * manifestDiff.groovy * * manifestDiff.groovy <first_jar_file> <second_jar_file> * * Script that compares the MANIFEST.MF files of two JAR files. */if(args.length < 2){   println "\nUSAGE: manifestDiff.groovy <first_jar_file> <second_jar_file>\n"   System.exit(-1)}TOTAL_WIDTH = 180COLUMN_WIDTH = TOTAL_WIDTH / 2- 3ROW_SEPARATOR = "-".multiply(TOTAL_WIDTH)importjava.util.jar.JarFiledef file1Name = args[0]def jar1File = newJarFile(file1Name)def num1Attrs = jar1File.manifest.mainAttributes.size()def file2Name = args[1]def jar2File = newJarFile(file2Name)def num2Attrs = jar2File.manifest.mainAttributes.size()println ROW_SEPARATORprintln "| ${file1Name.center(COLUMN_WIDTH)}| ${file2Name.center(COLUMN_WIDTH)} |"print "| ${(Integer.toString(num1Attrs) + (num1Attrs != 1 ? "attributes" : "attribute")).center(COLUMN_WIDTH)}|"println " ${(Integer.toString(num2Attrs) + (num2Attrs != 1 ? "atttributes" : "attribute")).center(COLUMN_WIDTH)} |"println ROW_SEPARATORif(jar1File.manifest != jar2File.manifest){   def manifest1Attrs = jar1File.manifest.mainAttributes   def manifest2Attrs = jar2File.manifest.mainAttributes   def attrsIn1ButNot2 = manifest1Attrs.keySet() - manifest2Attrs.keySet()   def attrsIn2ButNot1 = manifest2Attrs.keySet() - manifest1Attrs.keySet()   attrsIn1ButNot2.each   {      def attr1onlyStr = "${it}=${manifest1Attrs.get(it)}"      print "| ${attr1onlyStr.center(COLUMN_WIDTH)}| "      println "${"".center(attr1onlyStr.size() > COLUMN_WIDTH ? 2 * COLUMN_WIDTH - attr1onlyStr.size() : COLUMN_WIDTH)} |"   }   println ROW_SEPARATOR   attrsIn2ButNot1.each   {      def attr2onlyStr = "${it}=${manifest2Attrs.get(it)}"      print "| ${"".center(attr2onlyStr.size() > COLUMN_WIDTH ? 2 * COLUMN_WIDTH - attr2onlyStr.size() : COLUMN_WIDTH)}|"      println " ${attr2onlyStr.center(COLUMN_WIDTH)} |"   }   println ROW_SEPARATOR   manifest1Attrs.each   {      def key = it.key      if(it.value != manifest2Attrs.get(key) && !attrsIn1ButNot2.contains(it.key))      {         def attr1Str = "${key}=${manifest1Attrs.get(key)}"         print "| ${attr1Str.center(COLUMN_WIDTH)}"         def attr2Str = "${key}=${manifest2Attrs.get(key)}"         println "| ${attr2Str.center(COLUMN_WIDTH)} |"      }   }   println ROW_SEPARATOR}else{   println "Manifests deemed identical."} | 
Сценарий, показанный здесь, позволяет легко увидеть различия между содержимым файлов манифеста двух JAR-файлов. Общие характеристики, содержащие имя JAR и количество атрибутов в каждом файле манифеста, показаны в скрипте. Другие атрибуты манифеста отображаются в выходных данных, только если атрибут уникален для одного файла манифеста или если атрибут с таким же именем в каждом файле манифеста имеет другое значение для этого атрибута.
 Приведенный выше сценарий можно объединить со сценарием jarDiff.groovy о jarDiff.groovy я писал ранее, чтобы увидеть, чем отличаются два файла манифеста, когда этот сценарий определяет наличие различий. 
Это еще один пример того, почему Groovy является таким полезным скриптовым языком в средах разработки Java.