Статьи

Поиск недвижимости в банках с Groovy

В предыдущих публикациях в блоге я рассмотрел Поиск файлов JAR с помощью Groovy, чтобы найти записи (например, .class ), содержащиеся в JAR, и просмотр файла манифеста JAR с помощью Groovy . В этой статье я расскажу об использовании Groovy для поиска определенного свойства в файле свойств, содержащемся в JAR. Сценарий в этом посте ищет файлы JAR в предоставленном каталоге и его подкаталогах для файла свойств, содержащего указанное свойство.

Следующий скрипт Groovy использует несколько преимуществ Groovy для рекурсивного поиска в указанном каталоге и его подкаталогах файлов JAR, содержащих файлы свойств, которые содержат указанное свойство. Сценарий выводит соответствующие файлы JAR и записи их файлов свойств, которые содержат указанное свойство. Сценарий также показывает значение, которое установлено для каждого свойства в каждом соответствующем файле JAR / свойства.

findPropertiesInJars.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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#!/usr/bin/env groovy
 
/**
 * findPropertiesInJars.groovy
 *
 * findPropertiesInJars.groovy -d <<root_directories>> -p <<properties_to_search_for>>
 *
 * Script that looks for provided properties (assumed to be in files with
 * .properties extension) in JAR files (assumed to have .jar extensions) in the
 * provided directory and all of its subdirectories.
 */
 
def cli = new CliBuilder(
   usage: 'findPropertiesInJars.groovy -d <root_directories> -p <property_names_to_search_for>',
   header: '\nAvailable options (use -h for help):\n',
   footer: '\nInformation provided via above options is used to generate printed string.\n')
import org.apache.commons.cli.Option
cli.with
{
   h(longOpt: 'help', 'Help', args: 0, required: false)
   d(longOpt: 'directories', 'Directories to be searched', args: Option.UNLIMITED_VALUES, valueSeparator: ',', required: true)
   p(longOpt: 'properties', 'Property names to search for in JARs', args: Option.UNLIMITED_VALUES, valueSeparator: ',', required: true)
}
def opt = cli.parse(args)
if (!opt) return
if (opt.h) cli.usage()
 
def directories = opt.ds
def propertiesToSearchFor = opt.ps
 
import java.util.zip.ZipFile
import java.util.zip.ZipException
 
def matches = new TreeMap<String, Set<String>>()
directories.each
{ directory ->
   def dir = new File(directory)
   propertiesToSearchFor.each
   { propertyToFind ->
      dir.eachFileRecurse
      { file->
         if (file.isFile() && file.name.endsWith('jar'))
         {
            try
            {
               zip = new ZipFile(file)
               entries = zip.entries()
               entries.each
               { entry->
                  def entryName = entry.name
                  if (entryName.contains('.properties'))
                  {
                     def fullEntryName = file.canonicalPath + '!/' + entryName
                     def properties = new Properties()
                     try
                     {
                        def url = new URL('jar:file:' + File.separator + fullEntryName)
                        def jarConnection = (JarURLConnection) url.openConnection()
                        properties.load(jarConnection.inputStream)
                     }
                     catch (Exception exception)
                     {
                        println 'Unable to load properties from ${fullEntryName} - ${exception}'
                     }
                     if (properties.get(propertyToFind) != null)
                     {
                        def pathPlusMatch = '${file.canonicalPath}\n\t\t${entryName}\n\t\t${propertyToFind}=${properties.get(propertyToFind)}'
                        if (matches.get(propertyToFind))
                        {
                           matches.get(propertyToFind).add(pathPlusMatch)
                        }
                        else
                        {
                           def containingJars = new TreeSet<String>()
                           containingJars.add(pathPlusMatch)
                           matches.put(propertyToFind, containingJars)
                        }
                     }
                  }
               }
            }
            catch (ZipException zipEx)
            {
               println 'Unable to open JAR file ${file.name}'
            }
         }
      }
   }
}
 
matches.each
{ propertyName, containingJarNames ->
   println '\nProperty '${propertyName}' Found:'
   containingJarNames.each
   { containingJarName ->
      println '\t${containingJarName}'
   }
}

Когда вышеприведенный скрипт запускается для JAR, он перечисляет JAR с файлами свойств, которые имеют названное свойство и его назначенное значение. Снимок экрана, показанный ниже, демонстрирует выполнение сценария с использованием дистрибутива Apache Camel на моем компьютере, чтобы найти все свойства с именем ‘artifactId’ ( Maven ) в этих многочисленных файлах JAR.

Приведенный выше скрипт использует несколько возможностей Groovy. Например, способность Groovy напрямую использовать API-интерфейсы и библиотеки Java очевидна по всему сценарию с использованием таких классов, как ZipFile (для доступа к содержимому JAR), Properties (для доступа к содержимому файлов свойств), JarURLConnection (также для доступа к содержимому файлов свойств ), TreeSet (для легкой сортировки) и Apache Commons CLI (встроенный в Groovy для поддержки командной строки). Замыкания и лаконичный синтаксис Groovy также обеспечивают большую беглость и удобочитаемость.

Этот сценарий перехватывает исключения, даже если Groovy не требует перехвата каких-либо исключений (проверенных или во время выполнения). Причина этого в том, что необработанное исключение приведет к завершению скрипта. Улавливая любое обнаруженное исключение во время открытия каждого файла JAR или загрузки из файла свойств, исключение в этих случаях будет препятствовать загрузке только этого конкретного файла JAR или файла свойств, не останавливая обработку других.

Этот сценарий делает пару существенных предположений. Первое предположение состоит в том, что файлы JAR, которые нужно найти, имеют расширение .jar и что содержащиеся в них файлы свойств имеют расширения .properties . Сценарий использует встроенную поддержку CLI — единый флаг командной строки, позволяющий искать несколько каталогов и / или несколько имен свойств, разделяя несколько значений запятыми.

Иногда я хочу узнать, где определенное свойство указано в моем приложении, и этот сценарий позволяет легко найти, где именно это свойство указано в JAR-файлах в пути к классам приложения.

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