Java: торжественное обращение с jar и атрибутами MANIFEST.MF::Журнал СА 8.2008
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Подписка
Архив номеров
Где купить
Наука и технологии
Авторам
Рекламодателям
Контакты
   

  Опросы
  Статьи

Дата-центры  

Дата-центры: есть ли опасность утечки данных?

Российские компании уже несколько лет испытывают дефицит вычислительных мощностей. Рост числа проектов,

 Читать далее...

Событие  

В банке рассола ждет сисадмина с полей фрактал-кукумбер

Читайте впечатления о слете ДСА 2024, рассказанные волонтером и участником слета

 Читать далее...

Организация бесперебойной работы  

Бесперебойная работа ИТ-инфраструктуры в режиме 24/7 Как обеспечить ее в нынешних условиях?

Год назад ИТ-компания «Крок» провела исследование «Ключевые тренды сервисного рынка 2023». Результаты

 Читать далее...

Книжная полка  

Читайте и познавайте мир технологий!

Издательство «БХВ» продолжает радовать выпуском интересных и полезных, к тому же прекрасно

 Читать далее...

СУБД PostgreSQL  

СУБД Postgres Pro

Сертификация по новым требованиям ФСТЭК и роль администратора без доступа к данным

 Читать далее...

Критическая инфраструктура  

КИИ для оператора связи. Готовы ли компании к повышению уровня кибербезопасности?

Похоже, что провайдеры и операторы связи начали забывать о требованиях законодательства

 Читать далее...

Архитектура ПО  

Архитектурные метрики. Качество архитектуры и способность системы к эволюционированию

Обычно соответствие программного продукта требованиям мы проверяем через скоуп вполне себе понятных

 Читать далее...

Как хорошо вы это знаете  

Что вам известно о разработках компании ARinteg?

Компания ARinteg (ООО «АРинтег») – системный интегратор на российском рынке ИБ –

 Читать далее...

Графические редакторы  

Рисование абстрактных гор в стиле Paper Cut

Векторный графический редактор Inkscape – яркий представитель той прослойки open source, с

 Читать далее...

День сисадмина  

Учите матчасть! Или как стать системным администратором

Лето – время не только отпусков, но и хорошая возможность определиться с профессией

 Читать далее...

День сисадмина  

Живой айтишник – это всегда движение. Остановка смерти подобна

Наши авторы рассказывают о своем опыте и дают советы начинающим системным администраторам.

 Читать далее...

Виртуализация  

Рынок решений для виртуализации

По данным «Обзора российского рынка инфраструктурного ПО и перспектив его развития», сделанного

 Читать далее...

Книжная полка  

Как стать креативным и востребованным

Издательский дом «Питер» предлагает новинки компьютерной литературы, а также книги по бизнесу

 Читать далее...

Книжная полка  

От создания сайтов до разработки и реализации API

В издательстве «БХВ» недавно вышли книги, которые будут интересны системным администраторам, создателям

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 6237
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 6944
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

12.03.2018г.
Просмотров: 4230
Комментарии: 0
Глубокое обучение с точки зрения практика

 Читать далее...

12.03.2018г.
Просмотров: 3015
Комментарии: 0
Изучаем pandas

 Читать далее...

12.03.2018г.
Просмотров: 3811
Комментарии: 0
Программирование на языке Rust (Цветное издание)

 Читать далее...

19.12.2017г.
Просмотров: 3827
Комментарии: 0
Глубокое обучение

 Читать далее...

19.12.2017г.
Просмотров: 6323
Комментарии: 0
Анализ социальных медиа на Python

 Читать далее...

19.12.2017г.
Просмотров: 3174
Комментарии: 0
Основы блокчейна

 Читать далее...

19.12.2017г.
Просмотров: 3466
Комментарии: 0
Java 9. Полный обзор нововведений

 Читать далее...

16.02.2017г.
Просмотров: 7283
Комментарии: 0
Опоздавших не бывает, или книга о стеке

 Читать далее...

17.05.2016г.
Просмотров: 10649
Комментарии: 0
Теория вычислений для программистов

 Читать далее...

30.03.2015г.
Просмотров: 12370
Комментарии: 0
От математики к обобщенному программированию

 Читать далее...

18.02.2014г.
Просмотров: 14006
Комментарии: 0
Рецензия на книгу «Читаем Тьюринга»

 Читать далее...

13.02.2014г.
Просмотров: 9130
Комментарии: 0
Читайте, размышляйте, действуйте

 Читать далее...

12.02.2014г.
Просмотров: 7084
Комментарии: 0
Рисуем наши мысли

 Читать далее...

10.02.2014г.
Просмотров: 5393
Комментарии: 3
Страна в цифрах

 Читать далее...

18.12.2013г.
Просмотров: 4620
Комментарии: 0
Большие данные меняют нашу жизнь

 Читать далее...

18.12.2013г.
Просмотров: 3431
Комментарии: 0
Компьютерные технологии – корень зла для точки роста

 Читать далее...

04.12.2013г.
Просмотров: 3164
Комментарии: 0
Паутина в облаках

 Читать далее...

03.12.2013г.
Просмотров: 3405
Комментарии: 0
Рецензия на книгу «MongoDB в действии»

 Читать далее...

02.12.2013г.
Просмотров: 3030
Комментарии: 0
Не думай о минутах свысока

 Читать далее...

Друзья сайта  

 Java: торжественное обращение с jar и атрибутами MANIFEST.MF

Архив номеров / 2008 / Выпуск №8 (69) / Java: торжественное обращение с jar и атрибутами MANIFEST.MF

Рубрика: Программирование /  Программирование

Алексей Саенко

Java: торжественное обращение с jar
и атрибутами MANIFEST.MF

Java-приложения гораздо удобнее собирать в один jar-файл, нежели хранить сложную структуру нескольких тысяч файлов. Однако плюсы использования jar-файлов этим удобством не ограничиваются, иногда может возникнуть необходимость передавать параметры из манифеста.

Многие Java-приложения поставляются в виде одного или нескольких jar-файлов (Java ARchive), которые по сути являются обыкновенными zip-архивами. В них обычно, кроме байт-кода программы, размещаются дополнительные ресурсы и конфигурационные файлы.

Такой подход позволяет:

  • подписывать содержимое jar-файла, повышая таким образом уровень безопасности;
  • сокращать время загрузки апплетов за счет отсутствия необходимости открытия нового соединения для каждого файла;
  • сокращать объем приложения;
  • упростить процесс создания библиотеки;
  • осуществлять контроль версий.

Полноценно работать с технологией JAR можно как с помощью утилиты jar, входящей в состав JDK (Java Development Kit), так и с использованием классов JAR API.

Первый способ распространен повсеместно, в то время как второй, зачастую незаслуженно, обделен вниманием и, как показывает практика, напрасно – во многих случаях это может существенно облегчить жизнь разработчика. Именно поэтому в данной статье будут описаны несколько способов применения JAR API для вызова произвольных методов из jar-файла, записи и чтения атрибутов манифеста. (Манифест – (устар.) торжественное письменное обращение верховной власти к народу в связи с важным политическим событием, торжественной датой и т. д. (Толковый словарь русского языка).

Утилита jar

Прежде всего следует уделить некоторое внимание утилите jar (http://java.sun.com/javase/6/docs/technotes/tools/solaris/jar.html). Это консольное приложение, запускаемое с набором параметров.

Примеры вызова утилиты:

// Создание нового jar-файла

jar cf file.jar список_файлов

// Просмотр содержимого архива

jar tf file.jar

// Извлечение содержимого из jar-файла

jar xf file.jar

MANIFEST.MF

JAR File Specification (http://java.sun.com/javase/6/docs/technotes/guides/jar/jar.html), позволяет расположить в архиве file.jar только один манифест с дополнительной служебной информацией META-INF/MANIFEST.MF, представляющий собой текстовый файл в кодировке UTF-8. Если он не был задан при создании jar-файла, используется манифест, который по умолчанию содержит информацию о своей версии и JDK, в которой был создан конкретный jar-файл:

Manifest-Version: 1.0

Created-By: 1.6.0 (Sun Microsystems Inc.)

Условно содержимое можно разделить на главную группу (содержит определенные стандартами атрибуты, некоторые из них приведены в таблице 1) и индивидуальную группу (состав которой определяется произвольно).

Таблица 1. Атрибуты главной группы манифеста

Атрибут

Описание

Manifest-Version

Номер версии файла-манифеста. Определяется спецификацией как регулярное выражение следующего вида: цифра+{.цифра+}*

Created-By

Версия и поставщик платформы Java, с помощью которой был создан манифест. Автоматически генерируется утилитой jar

Signature-Version

Версия подписи jar-файла. Определяется так же, как и Manifest-Version

Class-Path

Относительные указатели ресурсов (URL) для всех используемых дополнительных классов и библиотек

Main-Class

Относительный путь к главному классу приложения, который должен содержать точку входа – метод main(String[] args). Значение атрибута не должно содержать расширение .class. Атрибут определяется для автономных настольных приложений, которые собраны в выполняемые jar-файлы, которые могут быть запущены виртуальной машиной Java напрямую командой: java -jar file.jar

Имена произвольных атрибутов могут содержать только цифры, строчные и заглавные буквы латинского алфавита и знак «_», а по длине существует ограничение – 70 символов. К значению атрибута никаких требований, кроме элементарной логики, не предъявляется.

Более подробно структуру и состав JAR и META-INF/MANIFEST.MF в рамках этого текста мы затрагивать не будем по той простой причине, что любой желающий может прочесть более подробно cпецификацию JAR.

Использование JAR API

В последней на текущий момент Java 1.6 к JAR API относятся классы пакета java.util.jar, а также классы java.net.JarURLConnection и java.net.URLClassLoader. Ограничимся рассмотрением наиболее используемых классов (см. таблицу 2).

Таблица 2. Наиболее используемые классы в JAR API

Полное название класса

Описание

java.util.jar.Attributes

Таблица соответствий между именем атрибута и его значением

java.util.jar.Attributes.Name

Перечисление в виде констант всех имен атрибутов главной группы

java.util.jar.JarEntry

Класс описывает элемент jar-файла, например, файл с расширением .class

java.util.jar.JarFile

Наследник класса java.util.zip.ZipFile с поддержкой манифеста. Используется для чтения содержимого jar-файла

java.util.jar.JarInputStream

Наследник класса java.util.zip.ZipInputStream с поддержкой манифеста. Используется для чтения содержимого jar-файла из любого входящего потока

java.util.jar.JarOutputStream

Наследник класса java.util.zip.ZipOutputStream с поддержкой записи манифеста. Используется для записи содержимого jar-файла в любой исходящий поток

java.util.jar.Manifest

Класс используется для работы с манифестом и его атрибутами

java.net.JarURLConnection

Соединение с jar-файлом или его элементом с помощью указателя ресурсов вида:
ar:<url_к_jar_файлу >!/{элемент_jar_файла}, например: jar:http://www.site.org/folder/file.jar!/org/site/Clazz.class

java.net.URLClassLoader

Используется для загрузки классов и ресурсов из classpath (может определяться, к примеру, атрибутом манифеста Class-Path)

Запуск методов класса

Прежде всего рассмотрим пример, который будет запускать метод public static void main(String[] args) из произвольного класса в jar-файле. Предположим, что у нас есть некий файл file.jar, который содержит класс pkg.Main:

package pkg;


public class Main {

    public static void main(String[] args) {

           System.out.println("main(): запущен");

    }

}

MANIFEST.MF архива имеет следующий вид:

Manifest-Version: 1.0

Created-By: 1.6.0_03-b05 (Sun Microsystems Inc.)

Main-Class: pkg.Main

Вначале необходимо получить URL по имени файла:

URL fileUrl = new File("file.jar").toURL();

URL url = new URL("jar", "", fileUrl + "!/");

Сам вызов осуществляется следующим образом:

public static final String MAIN_METHOD = "main";

public void runMainMethod(String className) throws Exception {

    String[] args = new String[1];

    Class clazz;

    Method mainMethod;

    // Создадим ClassLoader

    URLClassLoader urlClassLoader =

           new URLClassLoader(new URL[] { url });

    // Загрузка класса класслоадером

    clazz = urlClassLoader.loadClass(className);

    // Получение main-метода и проверка, является ли он точкой входа

    mainMethod = clazz.getMethod(MAIN_METHOD, args.getClass());

    mainMethod.setAccessible(true);

    int mods = mainMethod.getModifiers();

    if (mainMethod.getReturnType() != void.class

           || !Modifier.isStatic(mods) || !Modifier.isPublic(mods)) {

           throw new NoSuchMethodException(MAIN_METHOD);

    } else {

           // Запуск метода с объектом, у которого надо выполнить метод, и параметрами.

           // null показывает, что метод статический

           mainMethod.invoke(null, args);

    }

}

Теперь попробуем задействовать JAR API для решения несколько усложненной задачи – теперь необходимо запустить метод main() главного класса jar-файла. Для этого нам надо лишь вызвать уже имеющийся метод runMainMethod() с именем требуемого класса, которое можно получить из манифеста по имени атрибута Main-Class:

private String getMainClassName() throws IOException {

JarURLConnection connection = (JarURLConnection) url.openConnection();

Attributes attributes = connection.getMainAttributes();

return attributes.getValue(Attributes.Name.MAIN_CLASS);

}

После вызова метода runMainMethod() в консоли появится надпись:

main(): запущен

Генерация манифеста с атрибутами

После того как мы успешно запустили метод main() главного класса jar-файла, попробуем поработать с атрибутами манифеста. Начнем с создания манифеста, а затем попробуем прочитать записанные атрибуты. Итак, класс JarAttributeWriter будет генерировать все атрибуты:

import java.io.ByteArrayInputStream;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.util.jar.Manifest;

 

public class JarAttributeWriter {

private static final String LINE_TEMPLATE = "%s: %s\n";

 

// Метод генерирует текстовый файл – манифест с именем filename

public void generateManifest(String filename) {

    StringBuffer buf = new StringBuffer();

    buf.append(getLine("Manifest-Version", "1.0"));

    buf.append(getLine("Created-By", this.getClass().getName()));

    buf.append(getLine("Attribute_1", "Value_1"));

    buf.append(getLine("Attribute_2", "Value_2"));

    try {

           InputStream inputStream = new ByteArrayInputStream(buf.toString().getBytes("UTF-8"));

           Manifest manifest = new Manifest(inputStream);

           OutputStream outputStream = new FileOutputStream(filename);

           manifest.write(outputStream);

    } catch (IOException e) {

           e.printStackTrace();

    }

}

 

// Метод возвращает одну строку манифеста. Метод format() - аналог printf

// в C – осуществляет форматированный вывод

private String getLine(String attributeName, String attributeValue) {

    return String.format(LINE_TEMPLATE, attributeName, attributeValue);

}

}

В результате файл манифеста будет содержать:

 

Manifest-Version: 1.0

Created-By: JarAttributeWriter

Attribute_1: Value_1

Attribute_2: Value_2

Чтение атрибутов из манифеста

Получившийся файл можно использовать в качестве манифеста для jar-архива – это довольно просто, поэтому предположим, что этот манифест уже лежит в jar-файле и требуется считать из него все атрибуты или только некоторые. Эту работу будет выполнять класс JarAttributeReader:

import java.io.IOException;

import java.util.jar.Attributes;

import java.util.jar.JarFile;

 

public class JarAttributeReader {

    private static final String OUTPUT_TEMPLATE = "%s=%s";

 

    // Метод считывает все атрибуты из jar-файла filename

    Attributes getAllAttributes(String filename) throws IOException {

           JarFile jarFile;

           Attributes attributes;

 

           jarFile = new JarFile(filename);

           attributes = jarFile.getManifest().getMainAttributes();

           return attributes;

}

 

    // Метод печатает в консоли атрибуты со значениями

    void printAllAttributesWithValues(String filename) {

    try {

           Attributes attributes = getAllAttributes(filename);

           for (Object o : attributes.keySet()) {

                 System.out.println(String.format(OUTPUT_TEMPLATE, o, attributes.getValue(o.toString())));

    }

    } catch (IOException e) {

           e.printStackTrace();

    }

    }

 

}

В результате в консоли появится запись следующего вида:

 

Manifest-Version=1.0

Created-By=JarAttributeWriter

Attribute_1=Value_1

Attribute_2=Value_2

 

Заключение

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


Комментарии отсутствуют

Добавить комментарий

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-45
E-mail: sa@samag.ru