Статьи

Сравнение файлов манифеста с Groovy

В моем последнем посте обсуждалось сравнение высокоуровневого содержимого двух 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 = 180
COLUMN_WIDTH = TOTAL_WIDTH / 2 - 3
ROW_SEPARATOR = "-".multiply(TOTAL_WIDTH)
 
import java.util.jar.JarFile
 
def file1Name = args[0]
def jar1File = new JarFile(file1Name)
def num1Attrs = jar1File.manifest.mainAttributes.size()
def file2Name = args[1]
def jar2File = new JarFile(file2Name)
def num2Attrs = jar2File.manifest.mainAttributes.size()
 
println ROW_SEPARATOR
println "| ${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_SEPARATOR
 
if (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.

Ссылка: Сравнение файлов манифеста с Groovy от нашего партнера по JCG Дастина Маркса в блоге Inspired by Actual Events .