Volgograd

Волгоград Linux User Group

Организована 23 ноября 2002 года

Проект заморожен Птн Июл 6 02:11:14 MSD 2012


Вход:  Пароль:  

ГраблеВодство/LearnAndTranslate/JPackagePolicy


Это старая версия ГраблеВодство/LearnAndTranslate/JPackagePolicy за 2007-07-01 21:40:56..

JPackage Java™ infrastructure design and packaging policy


Nicolas Mailhot
JPackage Project
Ville Skyttä
JPackage Project

$Id: jpackage-1.5-policy.xhtml,v 1.2 2005/09/17 07:06:26 david Exp $

Резюме
Этот документ содержит политику упаковки в соответствии с JPackage cross-distribution RPM Java™ packaging project.



Оглавление документа




Почему?


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

Как следствие, приложения были проверены только с версиями компонентов, с которыми они были связаны. Вся Java-система страдает бесконечным дублированием одних и тех же модулей, объединение повторяющихся частей может быть кошмаром, так как они обязаны зависеть от тех же самых компонентов — только с различными и изощренно несовместимыми версиями#1. Любое обновление по безопасности или по совместимости должно быть выполнено для всех эти дублирующихся компонентов.

Эта проблема получена в результате текущей практики вложения расширений прямо в JVM. По прошествии некоторого времени, компонент, который мог нормально быть встроен в приложение, неожиданно начинает конфликтовать с частью JVM и приводить к коварным падениям и ошибкам.

Это не удивительно, что сложные Java системы имеют тенденцию костенеть очень быстро. И приводить к быстрому росту стоимости обслуживания, что в свою очередь приводит к падению интереса к поддержанию таких систем в рабочем состоянии. И в конечном итоге люди бросают этим заниматься.
Данная ситуация не совместима с типичной быстро развивающейся Linux-системой. Чтобы достигнуть своей цели, создания дружественных для пользователей и администраторов методов rpm упаковки Java приложений, JPackage Project должен развить свою системную инфраструктуру и строгие правила упаковки.


[1] Различные требования, различные ошибки
[2] For example when the system kernel or C core changes Java assumptions.



Глава 1. Общие правила


Будь модульным

По возможности модуль должен быть разбит на образующие компоненты. Компонент должен иметь уникальное имя и расположение. Только одна версия данного компонента должна быть установлена. Приложения, разделяющие одинаковые зависимости, должны зависеть от внешних пакетов, не встроенных версий.

====Be vendor and implementation agnostic====
Пользователь должен иметь возможность выбора между различными реализациями одного и того же компонента, в особенности когда их лицензионные условия не эквивалентны или когда их уровень законченности отличается. Необходимо учесть возможность параллельной установки таких компонентов, с возможностью самостояетльного выбора пользователем между ними или лучшего из них системой#3.
Be distribution agnostic
Пакеты должны работать на большинстве основных rpm-based дистрибутивах. Это означает следование стандартам, таких как Linux Standard Base, Filesystem Hierarchy Standard или freedesktop.org спецификациям

Прежде всего запрещено использование дистрибутивно-специфичных особенностей#4.

Отметим, что это – прагматическое чтение стандартов. Средства обслуживания не определены, но в основном находятся в состоянии готовности для использования в проекте#5, дистрибутивно-специфичные адаптации допускаются при условии их не вмешательства в общее использование.


[3] Основанные на лицензионных условиях, известные завершенности, относительное отсутствие ошибок, рекламные проникновения и так далее
[4] Как Mandrake'овская gprintf функция.
[5] Для примера rpm4 возможности, или Debian'ская система alternatives(8)...



Глава 2. Назначение имен

Имя пакета


Пакеты должны быть названы общим именем их оригинального проекта в нижнем регистре. Когда пакет предоставляет расширение, которое было в какой-то момент заложено в Java стандарте, -ext (как external) суффикс должен быть добавлен, для различия между именем пакета и именем расширения. И JVM, которое включает данное расширение, и автономный пакет расширения, должны иметь оригинальное название как virtual Provides.

JVM должны носить имя — java-standard_version-vendor. Оригинальное название с сайта не должно использоваться в связи с широкой практикой разброса в именовании от вендора к вендроу и от версии к версии.

Название Jar-файлов


  • Если пакет предоставляет только один jar, он должен иметь тоже название что и пакет, с добавлением версии продукта.

  • Безверсионная символьная ссылка, смотрящая на оригинальный файл тоже должна быть предоставлена (провайдена)

  • Если название проекта и часто используемое jar-имя отличаются, символьная ссылка на принятое имя должна так же быть предоставлена (провайдиться).

  • Если пакет состоит из нескольких jar'ов, их обычные названия также будут использоваться.

  • Если число jar'ов превышает два, или если они были предоставлены в виде монолитного jar'а, файлы должны быть помещены в поддиректорию с названием пакета (так же как и для одиночного jar'а).

  • Если проект предлагает выбор метода упаковки, между одни монолитным jar'ом или разбиением на несколько более мелких, упаковка с разбиением будет предпочтительнее.



Глава 3. Структура директорий


Основная структура директорий, предоставляемая пакетом jpackage-utils состоит из:

%{_javadir}

/usr/share/java

RPM макрос %{_javadir} задает главный jar-репозитарий. Исторически это была единственная директория, используемая 1.0 JPakage, прежде чем упаковочные ограничения привели к более сложной системе. Он обычно раскрывается в /usr/share/java.

Все jar-файлы и директории с jar-файлами, которые не зависят от конретной версии Java-стандарта или JNI должны быть установлены в %{_javadir}.

/usr/share/java-ext

От %{_javadir} мы получаем %{_javadir}-ext. Все jar-файлы и директории jar-файлов, которые зависят от конкретной версии Java-стандарта, но не от JNI должны быть установлены в %{_javadir}-ext.

/usr/share/java-x.y.z

Директории %{_javadir}-x.y.z содержат символьные ссылки на файлы или директории для всех элементов %{_javadir}-ext, которые действительны для x.y.z версии Java-стандарта. С тех пор как реализация обычно действительна для ряда повторений Java-стандартов, файл или директория в %{_javadir}-ext будет содержать несколько символьных ссылок ссылающихся на нее. Так же следует отметить безверсионные символьные ссылки: для двух jar'ов названных foo13.jar и foo14.jar, foo.jar символьная ссылка будет указывать на foo13.jar в %{_javadir}-1.3.0 и %{_javadir}-1.3.1, и foo14.jar в %{_javadir}-1.4.0, %{_javadir}-1.4.1 и %{_javadir}-1.4.2.

К сожалению, Java-стандарт как известно меняется довольно сильно между младшими версиями, поэтому мы должны учитывать полную версию и различия между %{_javadir}-1.4.0 и %{_javadir}-1.4.1.


/usr/share/java-utils

Используется для множества java-связанных скриптов и функций, включая главную библиотеку shell-функций java-functions.

%{_jnidir}: /usr/lib/java...

RPM макрос %{_jnidir} определяет главный JNI jar-репозитарий. Так же как и %{_javadir} разветвляется на ветки -ext и -x.y.z. Придерживается тех же правил что и %{_javadir}-ответвление, исключая, то что он содержит jar'ы, которые используют JNI.

%{_jnidir} обычно указывает на /usr/lib/java.

%{_jvmdir}

%{_libdir}/jvm: /usr/lib/jvm

RPM макрос %{_jvmdir} определяет корневую директорию, в которую устанавливаются различные JVM-системы. Обычно это /usr/lib/jvm

%{_libdir}/jvm-exports: /usr/lib/jvm-exports

От %{_jvmdir} мы переходим к %{_jvmdir}-exports. Каждая поддиректория %{_jvmdir} должна иметь соответствующую в %{_jvmdir}-exports. Они используются для регистрации Java-расширений связанных с SDK или RE символьными ссылками, указывающими внутрь JMV структуры в %{_jvmdir}.

Символьные ссылки должны указывать на фактический JVM jar-файл, предоставляющий расширение (хотя это не жесткое требование для работы системы), должны присутствовать версионные и не версионные варианты и следовать общим правилам назначения имен.

%{_libdir}/jvm-private: /usr/lib/jvm-private

%{_jvmdir}-private директория содержит «внутренние» JVM-файлы, но по каким-то причинам расположенные не в стандартной JVM-директории. Скрипты не должны ссылаться на эти файлы. Внутри данной директории расположены версионные директории в соответствии с их назначением.

Как пример «внутренних» файлов можно рассмотреть файлы политики JCE (Java Cryptography Extension), те что идут вместе с различными 1.4.x JVM'ами ограничены в функциональности и производители поставляют неограниченные по функциональности файлы политик отдельно. Зачастую эти файлы — часть какой-то версии Java-стандарта конкретного вендора (типа java-1.4.2-sun).



Различные версии jar'ов JCE-политик в дальнейшем управляются через систему альтернатив, использующую ссылку, которая указывает на соответствующий jar-файл в JVM jre/lib/security директории, с большим приоритетом на более функциональную версию чем та что принадлежит JVM.

%{_sysconfdir}/java: /etc/java

%{_sysconfdir}/java содержит основные файлы конфигурация, принадлежащие java-подсистеме, главным образом java.conf.

%{_javadocdir}

Это корень всех установленных javadoc документов. Его расположение и предполагаемое использование обсуждается в данный момент.

Директории зависимые от приложения


  • Собственные директории приложения должны располагаться в системе в соответствии с правилами Filesystem Hierarchy Standard

  • Если приложению необходимо свое файловое дерево, как в других операционных системах (а FHS требует, чтобы поддиректории были установленные в разные части системы), макрос %{_datadir}/appname должен быть использован как корневая-домашняя директория с символьными ссылками, указывающими на реальное расположение поддиректорий в системе. Конечно лучше изменить приложение, чтобы оно понимало правильное разделение файлов и отменяло пляску с символьными ссылками.


  • Велосипеды лучше не создавать. Если директория всегда имеет только один единственный подкаталог, избавьтесь от него#6
  • Если приложение использует classpath-компоненты, которые не являются jar-файлами, они должны быть установлены в собственную директорию приложения

zip, war и другие файлы архивов классов
Любой может столкнуться с другими типами архивов используемых в classpaths. Если прямой необходимости в использовании таких файлов нет, то следует конвертировать их в jar. Это особенно важно для zip-файлах, которые были одно время в широком использовании, но в последствии вышли из употребления.

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

  • Собственные jar-файлы
    Это предполагает, что стандартные правила, не могут быть использованы для построения classpath-приложения, таким образом эта часть должна быть обработана самим приложением или мантейнером пакета#7. Тем не менее, когда приложение может и будут читать собственный jar-репозитарий, мы действительно обеспечиваем средствами для управления частями репозитария, которые используются совместно с другими приложениями.


    [6] те не создавайте единственный подкаталог для библиотеки в %{_datadir}/appname, только потому что более сложные приложения делают это. Если он всегда будет один, используйте сразу %{_datadir}/appname.
    [7] Hardcoding classpath bits for example.



    Глава 4. Скрипты и выбор classpath при запуске


    Мы предполагаем что верные значения переменных окружения уже выставлены, по крайней мене $JAVA_HOME для выбора JVM в %{_jvmdir}, и в конечном счете $JAVACMD, $LD_ASSUME_KERNEL, $LANG, и $JAVA_COMPILER переменные.

    Исправить

    Текущая реализация данной политики не столь хороша как хотелось бы и тащит с собой кучу наследственного мусора. Нормальная реализация будет использовать значения переменных из ~/.apprc, с откатом в /etc/app.conf, хранением пользовательских переменных окружения в ~/.java и /etc/java/java.conf. Если $JAVA_HOME после этого будет не определена, то по умолчанию будет использовано значение /usr/lib/jvm/java.

    К сожалению, мы не делаем этого прямо сейчас.

    Основные правила разрешения

    Когда мы запрашиваем foo/bar-x.y, мы ищем foo/bar-x.y.jar jar-файл, затем foo/bar-x.y jar-директорию, в следующих местах:

    • %{_jvmdir}-exports/name Отображение JVM определено как $JAVA_HOME=%{_jvmdir}/name. Это JVM-специфичный репозитарий, в который вы вносим Java-расширения, принадлежащие ему.
    • %{_jnidir}-java_version Где java_version является JVM стандартным Java уровнем согласия как видно из

    • %{_javadir}-java_version java-version specific non-JNI jar repository.
    • %{_jnidir} Основной JNI jar-репозитарий.
    • %{_javadir} Основной jar-репозитарий.

    Если мы ничего не находим, поиск повторяется для foo/bar.jar, foo/bar, foo.jar, и наконец foo каталог. Заметим, поиск выполняется для пары jar/директория, т.е. поддиректория расположенная в более конкретном репозитарии будет всегда иметь превосходство перед jar с таким же именем, но расположенном в менее конкретном репозитарии.

    find-jar


    find-jar {объект}


    Команда find-jar проверяет расположение указанного объекта. Возвращает имя jar-файл или директории. Эта утилита предназначена исключительно для тестирования расположения объекта и не должна использоваться в скриптах. Данная команда является обязательной даже для определения classpath'а для единственного объекта, в связи с тем что поиск для единственного объекта может приводить к различным результатам, когда объект в итоге раскрывается в директорию.



    build-classpath


    build-classpath {объект...}


    Команда build-classpath находит classpath, следуя основным правилам разрешения. Аргументами команды — является список объектов. Если объект разрешается в директорию, все jar-файлы этой директории будут включены в classpath.



    Рекомендованная практика построения classpath, состоящей из достаточной и опциональной частей


    build-jar-repository


    build-jar-repository [[-s] | [--soft] | [--symbolic] | [-h] | [--hard] | [-c] | [--copy]] [[-p] | [--preserve-naming]] {директория} {объект...}


    Команда build-jar-repository создает структуру директорий из симлинков на jar-файлы, по следующим правилам. Принимает в качестве аргументов имя директории и список объектов. После чего попытается создать набор символьных ссылок [foo][bar]xxx.jar в указанной директории для каждого запрошенного foo/bar объекта#8. Особая структура имен символьных ссылок делает возможным определить были ли они созданным именно этой командой, и является необходимым условием для использования rebuild-jar-repository. Утилите build-jar-repository можно указать какого типа должны быть создаваемые объекты: символьной, жесткой ссылкой или копией файла. По умолчанию — создается символьная ссылка, другой тип должен быть использован только для сильно поврежденного ПО.

    Инкрементное использование
    build-jar-repository может быть свободно использован для одной и той же директории. Предыдущие симлинки не будут удалены. Удаление символьных ссылок в директории, производится только пользователем, утилита этого не делает.

    Задание имен, для безопасного перемещения
    Если вы хотите распространить директория с jar копиями или ссылками на них, вы можете использовать ключ --preserve-naming. При его использовании, build-jar-repository будет создавать файлы с именами наиболее близкими к оригинальным. Заметим, что это приведет к будущим проблемам при обновления этого репозитария. Не используйте данный ключ, пока вы точно не будете уверены, что вы делаете.

    --preserve-naming включает в себя --copy, пока не определено обратного.



    rebuild-jar-repository


    rebuild-jar-repository [[-s] | [--soft] | [--symbolic] | [-h] | [--hard] | [-c] | [--copy]] {директория}


    Команда rebuild-jar-repository обновляет jar-репозитарий, созданный build-jar-repository. Аргументом команды является имя директории, и предназначена для исправления символьных ссылок после изменения $JAVA_HOME, для совместимости с новым JVM. Опции для типа создаваемых объектов такие же что и у build-jar-repository.

    Смешанное использование
    Специфичные имена символьных ссылок, которые создаются build-jar-repository и rebuild-jar-repository позволяют смешивать автоматические ссылки, созданные в ручную и обычные файлы в директориях, обрабатываемых этими утилитами. Скрипты меняют только имена собственных ссылок



    Невозможность разрешения объекта...
    В отличии от build-jar-repository, rebuild-jar-repository будет создавать символьные ссылки. Это сделано для предотвращения потери объектов при сломанной java-подсистеме.#9 Созданная символьная ссылка указывает в «никуда» и всегда должна быть «поломанной».


    [8] Единичный объект может быть разрешен в директорию с большим числом jar-файлов.
    [9] Если устранить проблемы: установка нужных jar'ов или выбор более полной версии JVM, то rebuild-jar-repository отработает нормально, как-будто ничего и не случалось.