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.
По возможности модуль должен быть разбит на образующие компоненты. Компонент должен иметь уникальное имя и расположение. Только одна версия данного компонента должна быть установлена. Приложения, разделяющие одинаковые зависимости, должны зависеть от внешних пакетов, не встроенных версий.
Пользователь должен иметь возможность выбора между различными реализациями одного и того же компонента, в особенности когда их лицензионные условия не эквивалентны или когда их уровень законченности отличается. Необходимо учесть возможность параллельной установки таких компонентов, с возможностью самостояетльного выбора пользователем между ними или лучшего из них системой3.
Пакеты должны работать на большинстве основных rpm-based дистрибутивах. Это означает следование стандартам, таких как Linux Standard Base, Filesystem Hierarchy Standard или freedesktop.org спецификациям
Прежде всего запрещено использование дистрибутивно-специфичных особенностей4.
Отметим, что это – прагматическое чтение стандартов. Средства обслуживания не определены, но в основном находятся в состоянии готовности для использования в проекте5, дистрибутивно-специфичные адаптации допускаются при условии их не вмешательства в общее использование.
[3] Основанные на лицензионных условиях, известные завершенности, относительное отсутствие ошибок, рекламные проникновения и так далее
[4] Как Mandrake'овская gprintf функция.
[5] Для примера RPM 4 возможности, или Debian'ская система alternatives(8)...
Пакеты должны быть названы общим именем их оригинального проекта в нижнем регистре. Когда пакет предоставляет расширение, которое было в какой-то момент заложено в Java стандарте, -ext (как external) суффикс должен быть добавлен, для различия между именем пакета и именем расширения. И JVM, которое включает данное расширение, и автономный пакет расширения, должны иметь оригинальное название как virtual Provides.
JVM должны носить имя — java-standard_version-vendor. Оригинальное название с сайта не должно использоваться в связи с широкой практикой разброса в именовании от вендора к вендроу и от версии к версии.
Основная структура директорий, предоставляемая пакетом jpackage-utils состоит из:
RPM макрос %{_javadir} задает главный jar-репозитарий. Исторически это была единственная директория, используемая 1.0 JPakage, прежде чем упаковочные ограничения привели к более сложной системе. Он обычно раскрывается в /usr/share/java.
Все jar-файлы и директории с jar-файлами, которые не зависят от конретной версии Java-стандарта или JNI должны быть установлены в %{_javadir}.
От %{_javadir} мы получаем %{_javadir}-ext. Все jar-файлы и директории jar-файлов, которые зависят от конкретной версии Java-стандарта, но не от JNI должны быть установлены в %{_javadir}-ext.
Директории %{_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.
Используется для множества java-связанных скриптов и функций, включая главную библиотеку shell-функций java-functions.
RPM макрос %{_jnidir} определяет главный JNI jar-репозитарий. Так же как и %{_javadir} разветвляется на ветки -ext и -x.y.z. Придерживается тех же правил что и %{_javadir}-ответвление, исключая, то что он содержит jar'ы, которые используют JNI.
%{_jnidir} обычно указывает на /usr/lib/java.
RPM макрос %{_jvmdir} определяет корневую директорию, в которую устанавливаются различные JVM-системы. Обычно это /usr/lib/jvm
От %{_jvmdir} мы переходим к %{_jvmdir}-exports. Каждая поддиректория %{_jvmdir} должна иметь соответствующую в %{_jvmdir}-exports. Они используются для регистрации Java-расширений связанных с SDK или RE символьными ссылками, указывающими внутрь JMV структуры в %{_jvmdir}.
Символьные ссылки должны указывать на фактический JVM jar-файл, предоставляющий расширение (хотя это не жесткое требование для работы системы), должны присутствовать версионные и не версионные варианты и следовать общим правилам назначения имен.
%{_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 содержит основные файлы конфигурация, принадлежащие java-подсистеме, главным образом java.conf.
Это корень всех установленных javadoc документов. Его расположение и предполагаемое использование обсуждается в данный момент.
[6]
те не создавайте единственный подкаталог для библиотеки в %{_datadir}/appname, только потому что более сложные приложения делают это. Если он всегда будет один, используйте сразу %{_datadir}/appname.
[7]
Hardcoding classpath bits for example.
Мы предполагаем что верные значения переменных окружения уже выставлены, по крайней мене $JAVA_HOME для выбора JVM в %{_jvmdir}, и в конечном счете $JAVACMD, $LD_ASSUME_KERNEL, $LANG, и $JAVA_COMPILER переменные.
К сожалению, мы не делаем этого прямо сейчас.
Когда мы запрашиваем foo/bar-x.y, мы ищем foo/bar-x.y.jar jar-файл, затем foo/bar-x.y jar-директорию, в следующих местах:
Если мы ничего не находим, поиск повторяется для foo/bar.jar, foo/bar, foo.jar, и наконец foo каталог. Заметим, поиск выполняется для пары jar/директория, т.е. поддиректория расположенная в более конкретном репозитарии будет всегда иметь превосходство перед jar с таким же именем, но расположенном в менее конкретном репозитарии.
find-jar {объект}
Команда find-jar проверяет расположение указанного объекта. Возвращает имя jar-файл или директории. Эта утилита предназначена исключительно для тестирования расположения объекта и не должна использоваться в скриптах. Данная команда является обязательной даже для определения classpath'а для единственного объекта, в связи с тем что поиск для единственного объекта может приводить к различным результатам, когда объект в итоге раскрывается в директорию.
build-classpath {объект...}
Команда build-classpath находит classpath, следуя основным правилам разрешения. Аргументами команды — является список объектов. Если объект разрешается в директорию, все jar-файлы этой директории будут включены в classpath.
Рекомендованная практика построения classpath, состоящей из достаточной и опциональной частей
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 можно указать какого типа должны быть создаваемые объекты: символьной, жесткой ссылкой или копией файла. По умолчанию — создается символьная ссылка, другой тип должен быть использован только для сильно поврежденного ПО.
rebuild-jar-repository [[-s] | [--soft] | [--symbolic] | [-h] | [--hard] | [-c] | [--copy]] {директория}
Команда rebuild-jar-repository обновляет jar-репозитарий, созданный build-jar-repository. Аргументом команды является имя директории, и предназначена для исправления символьных ссылок после изменения $JAVA_HOME, для совместимости с новым JVM. Опции для типа создаваемых объектов такие же что и у build-jar-repository.
[8]
Единичный объект может быть разрешен в директорию с большим числом jar-файлов.
[9]
Если устранить проблемы: установка нужных jar'ов или выбор более полной версии JVM, то rebuild-jar-repository отработает нормально, как-будто ничего и не случалось.