Способ не претендует на исключительность, наверняка есть другие.
Итак, постановка задачи:
- версию jar-архива нужно хранить в самом архиве
- команда java -jar myprogramm.jar должна выводить версию архива
- для сборки проекта используется maven
- исходный код хранится в git
- версия jar'а должна включать:
- версию ПО
- ветку git
- id коммита
Проект собирается maven'ом. Исходники хранятся в git. Программист работает на линуксе (для Windows адаптировать будет не сложно). В принципе, инструментов достаточно. Осталось только собрать все вместе.
Алгоритм действий такой:
- скриптом вытаскиваем информацию из git'а и записываем в файл
- считываем свойства из файла
- записываем информацию о версии в manifest.mf при создании архива
- в manifest.mf указываем класс Version
- в классе Version создаем метод main, в котором вытаскиваем информацию из manifest.mf
git
Для получения информации из git'а используем отдельную программу createrepo.sh Её можно просто положить в корень проекта
#!/bin/sh branch=`git branch|grep \*|cut -d" " -f 2` commit=`git id` echo "buildNumber=${branch}.${commit}" > "$1"
maven
Теперь настраиваем наш pom.xml
Нужно определить свойство, которое будет хранить имя временного файла для версии из git'а.
<properties> <versionfile>${project.basedir}/version.properties</versionfile> </properties>
запуск скрипта
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2</version> <executions> <execution> <phase>initialize</phase> <goals> <goal>exec</goal> </goals> </execution> </executions> <configuration> <workingDirectory>${project.basedir}</workingDirectory> <executable>/bin/sh</executable> <arguments> <argument>createprop.sh</argument> <argument>${versionfile}</argument> </arguments> </configuration> </plugin>
чтение версии из файла
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>properties-maven-plugin</artifactId> <version>1.0-alpha-2</version> <executions> <execution> <phase>initialize</phase> <goals> <goal>read-project-properties</goal> </goals> <configuration> <files> <file>${versionfile}</file> </files> </configuration> </execution> </executions> </plugin>
запись информации в jar
<plugin> <artifactId>maven-jar-plugin</artifactId> <version>2.3.1</version> <configuration> <archive> <manifest> <addDefaultImplementationEntries>true</addDefaultImplementationEntries> <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries> </manifest> <manifestEntries> <Implementation-Version>${project.version}-${buildNumber}</Implementation-Version> <Main-Class>ru.habrahabr.sandello.Version</Main-Class> </manifestEntries> </archive> </configuration> </plugin>
удаление временного файла при чистке
<plugin> <artifactId>maven-clean-plugin</artifactId> <configuration> <filesets> <fileset> <directory>${project.basedir}</directory> <includes> <include>${versionfile}</include> </includes> </fileset> </filesets> </configuration> </plugin>
java
Создаем класс Version, который будет выводить версию архива
package ru.habrahabr.sandello ; import java.io.IOException; import java.io.InputStream; import java.util.jar.Attributes; import java.util.jar.Manifest; public class Version { public static void main(String[] args) { new Version().ver(); } private void ver() { final InputStream mfStream = getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF"); Manifest mf = new Manifest(); try { mf.read(mfStream); } catch (IOException e) { e.printStackTrace(); } Attributes atts = mf.getMainAttributes(); System.out.println("version: " + atts.getValue(Attributes.Name.IMPLEMENTATION_VERSION)); } }
Все готово. Собираем проект командой
mvn package.
В итоге имеем архив, который можно запускать
java -jar my.jar
Описанный способ, понятное дело, не без недостатков. К примеру, если целевая программа должна запускаться методом java -jar, то способ не подойдет. Придется его видоизменять: делать обработку аргументов или еще что-нибудь в этом духе. Или, целевая программа представляет собой набор файлов, которые выкладываются в Jboss или tomcat. Тоже придется видоизменять описанное решение.

