Hi,

I've realised after all the work that went into the 1.0 -> 1.5
transition we still didn't have any formal document describing how the
new system was supposed to work. So here is a quick overview. After
everyone had the time to comment on it I expect we'll include it in
jpackage-utils as %doc and/or on the web site (I suppose thinking that
documenting stuff will lead to more contributors is a harmless
delusion). The bits of still-relevant rpm packaging policy splattered on
the web site should probably also be integrated in this document.

Since we try not to stray too far from non-rpm linux systems, I've
included debian-java in CCs. It's been a long time since we synced with
them.

Anyway I know at least a few people want this since they've asked me
about the new scripts (repeatedly:).

Regards,

-- 
Nicolas Mailhot
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd";>
<html xmlns="http://www.w3.org/1999/xhtml";><head><meta 
http-equiv="Content-Type" content="text/html; charset=UTF-8" /><title>JPackage 
java infrastructure design and packaging policy</title><meta name="generator" 
content="DocBook XSL Stylesheets V1.61.0" /><meta name="description" 
content="&#10;This document describes the packaging policy followed by the 
JPackage cross-distribution rpm java packaging project.&#10;      " 
/></head><body><div class="book" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h1 class="title"><a id="id2616171"></a>JPackage 
java infrastructure design and packaging policy</h1></div><div><div 
class="author"><h3 class="author"><span class="firstname">Nicolas</span> <span 
class="surname">Mailhot</span></h3><div class="affiliation"><span 
class="orgname">JPackage Project<br /></span></div></div></div><div><div 
class="abstract"><p class="title"><b>Abstract</b></p><p>
This document describes the packaging policy followed by the <a 
href="http://www.jpackage.org/"; target="_top">JPackage</a> cross-distribution 
rpm java packaging project.
      </p></div></div></div><div></div><hr /></div><div class="toc"><p><b>Table 
of Contents</b></p><dl><dt><a href="#id2889586">Why ?</a></dt><dt>1. <a 
href="#id2876713">General rules</a></dt><dd><dl><dt><a href="#id2876720">Be 
modular</a></dt><dt><a href="#id2876738">Be vendor and implementation 
agnostic</a></dt><dt><a href="#id2876767">Be distribution 
agnostic</a></dt></dl></dd><dt>2. <a 
href="#id2827791">Naming</a></dt><dd><dl><dt><a href="#id2827798">Package 
naming</a></dt><dt><a href="#id2827832">Jar file 
naming</a></dt></dl></dd><dt>3. <a href="#id2826359">Directory 
structure</a></dt><dd><dl><dt><a 
href="#id2826375">%{_javadir}</a></dt><dd><dl><dt><a 
href="#id2826390">/usr/share/java</a></dt><dt><a 
href="#id2826448">/usr/share/java-ext</a></dt><dt><a 
href="#id2826498">/usr/share/java-x.y.z</a></dt><dt><a 
href="#id2826799">/usr/share/java-utils</a></dt></dl></dd><dt><a 
href="#id2826836">%{_jnidir}:
 /usr/lib/java</a></dt><dt><a 
href="#id2826920">%{_jvmdir}</a></dt><dd><dl><dt><a 
href="#id2826934">/usr/lib/jvm</a></dt><dt><a 
href="#id2826974">/usr/lib/jvm-ext</a></dt></dl></dd><dt><a 
href="#id2827061">%{_sysconfdir}/java:
 /etc/java</a></dt><dt><a 
href="#id2827106">%{_javadocdir}</a></dt></dl></dd><dt>4. <a 
href="#id2827129">Scripts and actual run-time classpath 
resolution</a></dt><dd><dl><dt><a href="#id2828018">General resolution 
rules</a></dt><dt><a href="#id2828238">find-jar</a></dt><dt><a 
href="#id2828286">build-classpath</a></dt><dt><a 
href="#id2828357">build-jar-repository</a></dt><dt><a 
href="#id2828455">rebuild-jar-repository</a></dt></dl></dd></dl></div><div 
class="list-of-examples"><p><b>List of Examples</b></p><dl><dt>3.1. <a 
href="#id2826662">Java standard version-specific repositories 
usage</a></dt></dl></div><div class="preface" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title"><a id="id2889586"></a>Why 
?</h2></div></div><div></div></div><p>
Clean Java packaging has historically been a daunting task. Lack of any 
standard addressing the physical location of files on the system combined with 
the common use of licensing terms that only allow free redistribution of key 
components as a part of a greater ensemble has let to the systematic release of 
self-sufficient applications with build-in copies of external components.
    </p><p>
As a consequence applications are only tested with the versions of the 
components they bundle, a complete Java system suffers from endless duplication 
of the same modules, and integrating multiple parts can be a nightmare since 
they are bound to depend on the same elements - only with different and subtly 
incompatible versions<sup>[<a id="id2889612" 
href="#ftn.id2889612">1</a>]</sup>. Any security or compatibility<sup>[<a 
id="id2889615" href="#ftn.id2889615">2</a>]</sup> upgrade must be performed for 
each of those duplicated elements.
    </p><p>
This problem is compounded by the current practice of folding extensions proper 
in the JVM itself after a while ; an element that could safely be embedded in a 
application will suddenly conflict with a JVM part and cause subtle failures.
    </p><p>
 It is not surprising then that complex Java systems tend to fossilize very 
quickly, with the cost of maintaining dependencies current growing too high so 
fast people basically give up on it.
    </p><p>
This situation is incompatible with your typical fast-evolving Linux platform. 
To attain its aim of user- and administrator-friendly rpm packaging of Java 
applications the JPackage Project had to evolve its own system infrastructure 
and strict packaging rules.
    </p><div class="footnotes"><br /><hr width="100" align="left" /><div 
class="footnote"><p><sup>[<a id="ftn.id2889612" href="#id2889612">1</a>] </sup>
Different requirements, different bugs.
        </p></div><div class="footnote"><p><sup>[<a id="ftn.id2889615" 
href="#id2889615">2</a>] </sup>
For example when the system kernel or C core changes Java assumptions.
        </p></div></div></div><div class="chapter" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title"><a 
id="id2876713"></a>Chapter 1. General 
rules</h2></div></div><div></div></div><div class="toc"><p><b>Table of 
Contents</b></p><dl><dt><a href="#id2876720">Be modular</a></dt><dt><a 
href="#id2876738">Be vendor and implementation agnostic</a></dt><dt><a 
href="#id2876767">Be distribution agnostic</a></dt></dl></div><div 
class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 
class="title" style="clear: both"><a id="id2876720"></a>Be 
modular</h2></div></div><div></div></div><p>
Whenever possible a module shall be broken out in its constituting elements. A 
given element will have a single name and location on the system. Only a single 
version of this element shall be installed. Applications sharing the same 
dependencies shall depend on external packages, not build-in versions.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2876738"></a>Be vendor and implementation 
agnostic</h2></div></div><div></div></div><p>
The user shall be able to choose between the different available 
implementations of the same element, especially when their licensing terms are 
not equivalent or their level of completeness unequal. Whenever possible it 
should be possible to install them in parallel, with the user able to select 
each of them specifically or let the system choose the best one<sup>[<a 
id="id2876755" href="#ftn.id2876755">3</a>]</sup>.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2876767"></a>Be distribution agnostic</h2></div></div><div></div></div><p>
Packages should work on most major rpm-based distributions. This means 
following standards like the <a href="http://www.linuxbase.org/"; 
target="_top">Linux Standard Base</a>, the <a 
href="http://www.pathname.com/fhs/"; target="_top">Filesystem Hierarchy 
Standard</a>, or <a href="http://www.freedesktop.org/"; 
target="_top">freedesktop.org</a> specifications.
      </p><p>
Above all usage of distribution-specific facilities<sup>[<a id="id2827751" 
href="#ftn.id2827751">4</a>]</sup> is <span 
class="emphasis"><em>forbidden</em></span>.
      </p><p>
Note this is a pragmatic reading of the standards. Facilities not specified but 
commonly found are readily used by the project<sup>[<a id="id2827776" 
href="#ftn.id2827776">5</a>]</sup> and distribution-specific adaptations are 
tolerated provided they do not interfere with common usage or a generic version 
is also available.
      </p></div><div class="footnotes"><br /><hr width="100" align="left" 
/><div class="footnote"><p><sup>[<a id="ftn.id2876755" href="#id2876755">3</a>] 
</sup>
Based on licensing terms, known completeness, relative bugginess, market 
penetration and so on.
          </p></div><div class="footnote"><p><sup>[<a id="ftn.id2827751" 
href="#id2827751">4</a>] </sup>
Like Mandrake <tt class="function">gprintf</tt> function.
          </p></div><div class="footnote"><p><sup>[<a id="ftn.id2827776" 
href="#id2827776">5</a>] </sup>
For example rpm 4 extensions, Debian's update-alternative system...
          </p></div></div></div><div class="chapter" lang="en" 
xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a 
id="id2827791"></a>Chapter 2. Naming</h2></div></div><div></div></div><div 
class="toc"><p><b>Table of Contents</b></p><dl><dt><a href="#id2827798">Package 
naming</a></dt><dt><a href="#id2827832">Jar file naming</a></dt></dl></div><div 
class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h2 
class="title" style="clear: both"><a id="id2827798"></a>Package 
naming</h2></div></div><div></div></div><p>
Packages shall be named after the common name of their origin project in small 
caps. When a package provides an extension that was folded at some point in the 
Java standard, the <span class="emphasis"><em>-ext</em></span> (as in external) 
suffix shall be appended to distinguish between the package name and the 
extension name. Both the JVMs including this extension and the standalone 
extension package shall then have the original name as a virtual Provides.
      </p><p>
JVM packages shall be named <span 
class="emphasis"><em>java-standard_version-vendor</em></span>. Original on-site
names are not followed since practice varies wildly from vendor to vendor and 
version to version.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2827832"></a>Jar file naming</h2></div></div><div></div></div><div 
class="orderedlist"><ol type="1"><li><p>
If a package provides a single jar it shall have the same name as the package 
itself, with appended product version.
          </p><div class="informalexample"><pre class="screen">
<tt class="filename">jaf-1.0.2.jar</tt>
            </pre></div></li><li><p>
A non-versioned symbolic link pointing on the original file shall also be 
provided.
          </p><div class="informalexample"><pre class="screen">
<tt class="filename">jaf-1.0.2.jar</tt>
<tt class="filename">jaf.jar</tt> → <tt class="filename">jaf-1.0.2.jar</tt>
            </pre></div></li><li><p>
If the project name and the commonly used jar name differ a symbolic link with 
the usual name shall also be provided.
          </p><div class="informalexample"><pre class="screen">
<tt class="filename">jaf-1.0.2.jar</tt>
<tt class="filename">jaf.jar</tt> → <tt class="filename">jaf-1.0.2.jar</tt>
<tt class="filename">activation.jar</tt> → <tt 
class="filename">jaf-1.0.2.jar</tt>
            </pre></div></li><li><p>
If the package provides several jars their usual names will be used.
          </p><div class="informalexample"><pre class="screen">
<tt class="filename">ant-1.5.3.jar</tt>
<tt class="filename">ant.jar</tt> → <tt class="filename">ant-1.5.3.jar</tt>
<tt class="filename">ant-optional-1.5.3.jar</tt>
<tt class="filename">ant-optional.jar</tt> → <tt 
class="filename">ant-optional-1.5.3.jar</tt>
            </pre></div></li><li><p>
If the number of provided jars exceeds two or if they were at a point provided 
in a single monolithic jar the files should be placed in a sub-directory named 
after the package (as for a single jar).
          </p><div class="informalexample"><pre class="screen">
<tt class="filename">javamail</tt>
<tt class="filename">javamail/imap-1.3.jar</tt>
<tt class="filename">javamail/imap.jar</tt> → <tt 
class="filename">imap-1.3.jar</tt>
<tt class="filename">javamail/mailapi-1.3.jar</tt>
<tt class="filename">javamail/mailapi.jar</tt> → <tt 
class="filename">mailapi-1.3.jar</tt>
<tt class="filename">javamail/pop3-1.3.jar</tt>
<tt class="filename">javamail/pop3.jar</tt> → <tt 
class="filename">pop3-1.3.jar</tt>
<tt class="filename">javamail/smtp-1.3.jar</tt>
<tt class="filename">javamail/smtp.jar</tt> → <tt 
class="filename">smtp-1.3.jar</tt>
            </pre></div></li><li><p>
If a project offers the choice of packaging it as a single monolithic jar or 
several ones, the split packaging will be prefered.
          </p></li></ol></div></div></div><div class="chapter" lang="en" 
xml:lang="en"><div class="titlepage"><div><div><h2 class="title"><a 
id="id2826359"></a>Chapter 3. Directory 
structure</h2></div></div><div></div></div><div class="toc"><p><b>Table of 
Contents</b></p><dl><dt><a href="#id2826375">%{_javadir}</a></dt><dd><dl><dt><a 
href="#id2826390">/usr/share/java</a></dt><dt><a 
href="#id2826448">/usr/share/java-ext</a></dt><dt><a 
href="#id2826498">/usr/share/java-x.y.z</a></dt><dt><a 
href="#id2826799">/usr/share/java-utils</a></dt></dl></dd><dt><a 
href="#id2826836">%{_jnidir}:
 /usr/lib/java</a></dt><dt><a 
href="#id2826920">%{_jvmdir}</a></dt><dd><dl><dt><a 
href="#id2826934">/usr/lib/jvm</a></dt><dt><a 
href="#id2826974">/usr/lib/jvm-ext</a></dt></dl></dd><dt><a 
href="#id2827061">%{_sysconfdir}/java:
 /etc/java</a></dt><dt><a 
href="#id2827106">%{_javadocdir}</a></dt></dl></div><p>
Core directory structure is provided by the <span 
class="emphasis"><em>jpackage-utils</em></span> package. It consists of:
    </p><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2826375"></a><tt 
class="systemitem">%{_javadir}</tt></h2></div></div><div></div></div><div 
class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 
class="title"><a id="id2826390"></a><tt 
class="filename">/usr/share/java</tt></h3></div></div><div></div></div><p>
The <tt class="systemitem">%{_javadir}</tt> rpm macro defines the main jar 
repository. Historically it was the sole directory used by the 1.0 JPackage 
distribution, before packaging constraints forced a more complex system. It 
usually expands into <tt class="filename">/usr/share/java</tt>.
        </p><p>
All jar files and directories of jar files that do not depend on a particular 
Java standard version or JNI shall be installed in <tt 
class="filename">%{_javadir}</tt>.
        </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h3 class="title"><a id="id2826448"></a><tt 
class="filename">/usr/share/java-ext</tt></h3></div></div><div></div></div><p>
From <tt class="systemitem">%{_javadir}</tt> we derive <tt 
class="filename">%{_javadir}-ext</tt>. All jar files and directories of jar 
files that depend on a particular Java standard version but not JNI shall be 
installed in <tt class="filename">%{_javadir}-ext</tt>.
        </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h3 class="title"><a id="id2826498"></a><tt 
class="filename">/usr/share/java-x.y.z</tt></h3></div></div><div></div></div><p>
We also derive the <tt class="filename">%{_javadir}-x.y.z</tt> directories. 
They contain symlinks to files or directories of <tt 
class="filename">%{_javadir}-ext</tt> for all elements that are valid for the 
x.y.z Java standard version. Since an implementation is usually valid for a 
range of Java standard iterations, a file or directory in <tt 
class="filename">%{_javadir}-ext</tt> will usually have several symbolic links 
pointing to it. Also of note are the non-versioned symlinks : for two jars 
named <tt class="filename">foo13.jar</tt> and <tt 
class="filename">foo14.jar</tt>, the <tt class="filename">foo.jar</tt> symlink 
will point to <tt class="filename">foo13.jar</tt> in <tt 
class="filename">%{_javadir}-1.3.0</tt> and <tt 
class="filename">%{_javadir}-1.3.1</tt>, and <tt 
class="filename">foo14.jar</tt> in <tt class="filename">%{_javadir}-1.4.0</tt>, 
<tt class="filename">%{_javadir}-1.4.1</tt> and <tt 
class="filename">%{_javadir}-1.4.2</tt>.
        </p><p>
Unfortunately the Java standard has been known to change enough between minor 
versions that we must take into account the full version and distinguish 
between <tt class="filename">%{_javadir}-1.4.0</tt> and <tt 
class="filename">%{_javadir}-1.4.1</tt>.
        </p><div class="example"><a id="id2826662"></a><p 
class="title"><b>Example 3.1. Java standard version-specific repositories 
usage</b></p><pre class="screen">
<tt class="filename">/usr/share/java-ext/jsse</tt>
<tt class="filename">/usr/share/java-ext/jsse/jcert-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-ext/jsse/jcert.jar</tt> → <tt 
class="filename">jcert-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-ext/jsse/jnet-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-ext/jsse/jnet.jar</tt> → <tt 
class="filename">jnet-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-ext/jsse/jsse-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-ext/jsse/jsse.jar</tt> → <tt 
class="filename">jsse-1.0.3.01.jar</tt>
<tt class="filename">/usr/share/java-1.3.0/jsse</tt> → <tt 
class="filename">/usr/share/java-ext/jsse</tt>
<tt class="filename">/usr/share/java-1.3.1/jsse</tt> → <tt 
class="filename">/usr/share/java-ext/jsse</tt>
            </pre></div></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h3 class="title"><a id="id2826799"></a><tt 
class="filename">/usr/share/java-utils</tt></h3></div></div><div></div></div><p>
We also derive <tt class="filename">%{_javadir}-utils</tt>. It is used to host 
java-related scripts and functions, including the main shell-script function 
library <tt class="filename">java-functions</tt>.
        </p></div></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2826836"></a><tt class="systemitem">%{_jnidir}</tt>:
 <tt class="filename">/usr/lib/java</tt></h2></div></div><div></div></div><p>
The <tt class="systemitem">%{_jnidir}</tt> rpm macro defines the main JNI jar 
repository. Like <tt class="systemitem">%{_javadir}</tt> it is declined in -ext 
and -x.y.z variants. It follows exactly the same rules as the <tt 
class="systemitem">%{_javadir}</tt>-derived tree structure, except that it 
hosts jars that use JNI.
      </p><p>
<tt class="systemitem">%{_jnidir}</tt> usually expands into <tt 
class="filename">/usr/lib/java</tt>.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2826920"></a><tt 
class="systemitem">%{_jvmdir}</tt></h2></div></div><div></div></div><div 
class="section" lang="en" xml:lang="en"><div class="titlepage"><div><div><h3 
class="title"><a id="id2826934"></a><tt 
class="filename">/usr/lib/jvm</tt></h3></div></div><div></div></div><p>
The <tt class="systemitem">%{_jvmdir}</tt> rpm macro defines the root directory 
under which the different system JVMs are installed. It usually expands into 
<tt class="filename">/usr/lib/jvm</tt>.
        </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h3 class="title"><a id="id2826974"></a><tt 
class="filename">/usr/lib/jvm-ext</tt></h3></div></div><div></div></div><p>
From <tt class="systemitem">%{_jvmdir}</tt> we derive <tt 
class="filename">%{_jvmdir}-ext</tt>. Each subdirectory of <tt 
class="filename">%{_jvmdir}</tt> must have a twin in <tt 
class="filename">%{_jvmdir}-ext</tt>. It is used to register Java extensions 
bundled with the <span class="acronym">SDK</span> or <span 
class="acronym">RE</span> with symbolic links pointing inside the JVM structure 
in <tt class="filename">%{_jvmdir}</tt>.
        </p><p>
The symbolic links shall point to the actual in-JVM jar file providing the 
extension (though that is not strictly necessary for the system to work), be 
available in versioned and non-versioned versions and follow general naming 
rules.
        </p></div></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2827061"></a><tt class="systemitem">%{_sysconfdir}</tt>/java:
 <tt class="filename">/etc/java</tt></h2></div></div><div></div></div><p>
<tt class="filename">%{_sysconfdir}/java</tt> hosts the general configuration 
files related to the java subsystem, mainly <tt class="filename">java.conf</tt>.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2827106"></a><tt 
class="systemitem">%{_javadocdir}</tt></h2></div></div><div></div></div><p>
This is the root of all installed javadoc documentation. It's location and 
intended usage are debated right now.
      </p></div></div><div class="chapter" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title"><a 
id="id2827129"></a>Chapter 4. Scripts and actual run-time classpath 
resolution</h2></div></div><div></div></div><div class="toc"><p><b>Table of 
Contents</b></p><dl><dt><a href="#id2828018">General resolution 
rules</a></dt><dt><a href="#id2828238">find-jar</a></dt><dt><a 
href="#id2828286">build-classpath</a></dt><dt><a 
href="#id2828357">build-jar-repository</a></dt><dt><a 
href="#id2828455">rebuild-jar-repository</a></dt></dl></div><p>
We assume the correct environment variables have already been set, ie at least 
<tt class="envar">$JAVA_HOME</tt> to select a JVM in <tt 
class="filename">%{_jvmdir}</tt>, and eventually the relevant <tt 
class="envar">$JAVACMD</tt>, <tt class="envar">$LD_ASSUME_KERNEL</tt>, <tt 
class="envar">$LANG</tt>, and <tt class="envar">$JAVA_COMPILER</tt> variables.
    </p><div class="warning" style="margin-left: 0.5in; margin-right: 
0.5in;"><h3 class="title">FIXME</h3><p>
The current implementation is not sane and carries a lot of legacy garbage. A 
clean implementation would be to read these values in <tt 
class="filename">~/.apprc</tt>, falling back on <tt 
class="filename">/etc/app.conf</tt>, the user environment, <tt 
class="filename">~/.java</tt> and <tt 
class="filename">/etc/java/java.conf</tt>. If <tt class="envar">$JAVA_HOME</tt> 
was still undefined then, use<tt class="filename">/usr/lib/jvm/java</tt> as 
default.
      </p><p>
Unfortunately we are not doing so right now.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2828018"></a>General resolution rules</h2></div></div><div></div></div><p>
When queried for <span class="emphasis"><em>foo/bar-x.y</em></span> we search 
for the <tt class="filename">foo/bar-x.y.jar</tt> jar file, then the <tt 
class="filename">foo/bar-x.y</tt> jar directory in the following locations:
      </p><div class="itemizedlist"><ul type="disc"><li><p><b><tt 
class="filename">%{_jvmdir}-ext/name</tt>. </b>
The shadow of the JVM defined by <tt class="envar">$JAVA_HOME</tt>=<tt 
class="filename">%{_jvmdir}/name</tt>. This is the JVM-specific repository 
where we register the Java extensions it includes.
            </p></li><li><p><b><tt 
class="filename">%{_jnidir}/java-version</tt>. </b>
Where <span class="emphasis"><em>java-version</em></span> is the JVM standard 
Java compliance level as deduced from
</p><pre class="screen"><tt class="prompt">[EMAIL PROTECTED] dir]$</tt> <b 
class="command">$JAVACMD</b> <tt class="option">-version</tt></pre><p>
            </p></li><li><p><b><tt 
class="filename">%{_javadir}/java-version</tt>. </b>
The java-version specific non-JNI jar repository.
            </p></li><li><p><b><tt class="filename">%{_javadir}</tt>. </b>
The general jar repository.
            </p></li></ul></div><p>
If we didn't find anything, the search is repeated for <tt 
class="filename">foo/bar.jar</tt>, <tt class="filename">foo/bar</tt>, <tt 
class="filename">foo.jar</tt> then at last the <tt class="filename">foo</tt> 
directory. Note the scan is performed for jar/directory pairs ie a subdirectory 
located in a more specific repository will always have precedence on a jar with 
the same name located in a less specific repository.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2828238"></a><b 
class="command">find-jar</b></h2></div></div><div></div></div><div 
class="cmdsynopsis"><p><tt class="command">find-jar</tt>  {element}</p></div><p>
The <b class="command">find-classpath</b> command tests the resolution of a 
given element. If successful it will return a jar file or a directory. It is 
solely intended for testing resolution and should not be used in scripts. Even 
for single-element classpath building the following command is preferred, since 
single-element searches can produce multiple file results when resolving into a 
directory.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2828286"></a><b 
class="command">build-classpath</b></h2></div></div><div></div></div><div 
class="cmdsynopsis"><p><tt class="command">build-classpath</tt>  
{element...}</p></div><p>
The <b class="command">build-classpath</b> command builds a standard classpath 
following the general resolution rules. It takes a list of elements as 
arguments. If an element resolves in a directory, all its children jar files 
are included in the classpath.
      </p><p>
Like the following command it will fail, return an non-zero error code and 
write to the error console if one or more of the requested elements were not 
found. Therefore for a classpath composed of required and optional parts 
recommended building practice is the following:
     </p><div class="informalexample"><pre class="programlisting">
CLASSPATH=$(build-classpath list_of_required_elements):$(build-classpath 
list_of_optional_elements 2&gt; /dev/null)
        </pre></div></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2828357"></a><b 
class="command">build-jar-repository</b></h2></div></div><div></div></div><div 
class="cmdsynopsis"><p><tt class="command">build-jar-repository</tt>  
{directory} {element...}</p></div><p>
The <b class="command">build-jar-repository</b> command constructs a flat 
directory of jar file symlinks following the same rules. It takes a directory 
name followed by a list of elements as arguments. It will try to create a <tt 
class="filename">[foo][bar]xxx.jar</tt> set of symbolic links in the target 
directory for each <span class="emphasis"><em>foo/bar</em></span> requested 
element<sup>[<a id="id2828427" href="#ftn.id2828427">6</a>]</sup>. The special 
symlink naming makes it possible to recognize they were created by this command 
and is required for the following command.
      </p><p>
<b class="command">build-jar-repository</b> can be safely used on the same 
directory several times. Previous symlinks won't be removed. If one wants to 
reset the directory the symbolic links must be cleaned up manually.
      </p></div><div class="section" lang="en" xml:lang="en"><div 
class="titlepage"><div><div><h2 class="title" style="clear: both"><a 
id="id2828455"></a><b 
class="command">rebuild-jar-repository</b></h2></div></div><div></div></div><div
 class="cmdsynopsis"><p><tt class="command">rebuild-jar-repository</tt>  
{directory}</p></div><p>
The <b class="command">rebuild-jar-repository</b> command refreshes a jar 
repository created with <b class="command">build-jar-repository</b>. It takes 
the directory name as argument. It is intended to be run after <tt 
class="envar">$JAVA_HOME</tt> was changed to insure all symlinked jar files are 
still compatible with the new JVM.
      </p></div><div class="footnotes"><br /><hr width="100" align="left" 
/><div class="footnote"><p><sup>[<a id="ftn.id2828427" href="#id2828427">6</a>] 
</sup>
Remember, a single element can resolve in a full directory of jar files.
          </p></div></div></div></div></body></html>
<?xml version='1.0'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
                      "http://www.docbook.org/xml/4.1.2/docbookx.dtd";>
<book lang="en">
  <bookinfo>
    <title>JPackage java infrastructure design and packaging policy</title>
    <author>
      <firstname>Nicolas</firstname>
      <surname>Mailhot</surname>
      <affiliation><orgname>JPackage Project</orgname></affiliation>
    </author>
    <abstract>
      <para>
This document describes the packaging policy followed by the <ulink url="http://www.jpackage.org/";>JPackage</ulink> cross-distribution rpm java packaging project.
      </para>
    </abstract>
  </bookinfo>

  <preface>
    <title>Why ?</title>

    <para>
Clean Java packaging has historically been a daunting task. Lack of any standard addressing the physical location of files on the system combined with the common use of licensing terms that only allow free redistribution of key components as a part of a greater ensemble has let to the systematic release of self-sufficient applications with build-in copies of external components.
    </para>
    <para>
As a consequence applications are only tested with the versions of the components they bundle, a complete Java system suffers from endless duplication of the same modules, and integrating multiple parts can be a nightmare since they are bound to depend on the same elements - only with different and subtly incompatible versions<footnote>
        <para>
Different requirements, different bugs.
	</para>
      </footnote>. Any security or compatibility<footnote>
	<para>
For example when the system kernel or C core changes Java assumptions.
        </para>
      </footnote> upgrade must be performed for each of those duplicated elements.
    </para>
    <para>
This problem is compounded by the current practice of folding extensions proper in the JVM itself after a while ; an element that could safely be embedded in a application will suddenly conflict with a JVM part and cause subtle failures.
    </para>
    <para>
 It is not surprising then that complex Java systems tend to fossilize very quickly, with the cost of maintaining dependencies current growing too high so fast people basically give up on it.
    </para>
    <para>
This situation is incompatible with your typical fast-evolving Linux platform. To attain its aim of user- and administrator-friendly rpm packaging of Java applications the JPackage Project had to evolve its own system infrastructure and strict packaging rules.
    </para>
  </preface>

  <chapter>
    <title>General rules</title>

    <section>
      <title>Be modular</title>

      <para>
Whenever possible a module shall be broken out in its constituting elements. A given element will have a single name and location on the system. Only a single version of this element shall be installed. Applications sharing the same dependencies shall depend on external packages, not build-in versions.
      </para>
    </section>

    <section>
      <title>Be vendor and implementation agnostic</title>

      <para>
The user shall be able to choose between the different available implementations of the same element, especially when their licensing terms are not equivalent or their level of completeness unequal. Whenever possible it should be possible to install them in parallel, with the user able to select each of them specifically or let the system choose the best one<footnote>
	  <para>
Based on licensing terms, known completeness, relative bugginess, market penetration and so on.
          </para>
	</footnote>.
      </para>

    </section>

    <section>
      <title>Be distribution agnostic</title>

      <para>
Packages should work on most major rpm-based distributions. This means following standards like the <ulink url="http://www.linuxbase.org/";>Linux Standard Base</ulink>, the <ulink url="http://www.pathname.com/fhs/";>Filesystem Hierarchy Standard</ulink>, or <ulink url="http://www.freedesktop.org/";>freedesktop.org</ulink> specifications.
      </para>

      <para>
Above all usage of distribution-specific facilities<footnote>
	  <para>
Like Mandrake <function>gprintf</function> function.
          </para>
	</footnote> is <emphasis>forbidden</emphasis>.
      </para>

      <para>
Note this is a pragmatic reading of the standards. Facilities not specified but commonly found are readily used by the project<footnote>
	  <para>
For example rpm 4 extensions, Debian's update-alternative system...
          </para>
	</footnote> and distribution-specific adaptations are tolerated provided they do not interfere with common usage or a generic version is also available.
      </para>
    </section>
  </chapter>

  <chapter>
    <title>Naming</title>

    <section>
      <title>Package naming</title>

      <para>
Packages shall be named after the common name of their origin project in small caps. When a package provides an extension that was folded at some point in the Java standard, the <emphasis>-ext</emphasis> (as in external) suffix shall be appended to distinguish between the package name and the extension name. Both the JVMs including this extension and the standalone extension package shall then have the original name as a virtual Provides.
      </para>

      <para>
JVM packages shall be named <emphasis>java-standard_version-vendor</emphasis>. Original on-site
names are not followed since practice varies wildly from vendor to vendor and version to version.
      </para>

    </section>

    <section>
      <title>Jar file naming</title>

      <orderedlist>
	<listitem>
	  <para>
If a package provides a single jar it shall have the same name as the package itself, with appended product version.
          </para>
	  <informalexample>
	    <screen>
<filename>jaf-1.0.2.jar</filename>
            </screen>
	  </informalexample>
	</listitem>
	<listitem>
	  <para>
A non-versioned symbolic link pointing on the original file shall also be provided.
          </para>
	  <informalexample>
	    <screen>
<filename>jaf-1.0.2.jar</filename>
<filename class="symlink">jaf.jar</filename> &rarr; <filename>jaf-1.0.2.jar</filename>
            </screen>
	  </informalexample>
	</listitem>
	<listitem>
	  <para>
If the project name and the commonly used jar name differ a symbolic link with the usual name shall also be provided.
          </para>
	  <informalexample>
	    <screen>
<filename>jaf-1.0.2.jar</filename>
<filename class="symlink">jaf.jar</filename> &rarr; <filename>jaf-1.0.2.jar</filename>
<filename class="symlink">activation.jar</filename> &rarr; <filename>jaf-1.0.2.jar</filename>
            </screen>
	  </informalexample>
	</listitem>
	<listitem>
	  <para>
If the package provides several jars their usual names will be used.
          </para>
	  <informalexample>
	    <screen>
<filename>ant-1.5.3.jar</filename>
<filename class="symlink">ant.jar</filename> &rarr; <filename>ant-1.5.3.jar</filename>
<filename>ant-optional-1.5.3.jar</filename>
<filename class="symlink">ant-optional.jar</filename> &rarr; <filename>ant-optional-1.5.3.jar</filename>
            </screen>
	  </informalexample>
	</listitem>
	<listitem>
	  <para>
If the number of provided jars exceeds two or if they were at a point provided in a single monolithic jar the files should be placed in a sub-directory named after the package (as for a single jar).
          </para>
	  <informalexample>
	    <screen>
<filename class="directory">javamail</filename>
<filename>javamail/imap-1.3.jar</filename>
<filename class="symlink">javamail/imap.jar</filename> &rarr; <filename>imap-1.3.jar</filename>
<filename>javamail/mailapi-1.3.jar</filename>
<filename class="symlink">javamail/mailapi.jar</filename> &rarr; <filename>mailapi-1.3.jar</filename>
<filename>javamail/pop3-1.3.jar</filename>
<filename class="symlink">javamail/pop3.jar</filename> &rarr; <filename>pop3-1.3.jar</filename>
<filename>javamail/smtp-1.3.jar</filename>
<filename class="symlink">javamail/smtp.jar</filename> &rarr; <filename>smtp-1.3.jar</filename>
            </screen>
	  </informalexample>
        </listitem>
	<listitem>
	  <para>
If a project offers the choice of packaging it as a single monolithic jar or several ones, the split packaging will be prefered.
          </para>
	</listitem>
      </orderedlist>

    </section>

  </chapter>

  <chapter>
    <title>Directory structure</title>

    <para>
Core directory structure is provided by the <emphasis>jpackage-utils</emphasis> package. It consists of:
    </para>

    <section>
      <title><systemitem class="macro">%{_javadir}</systemitem></title>

      <section>
	<title><filename class="directory">/usr/share/java</filename></title>

	<para>
The <systemitem class="macro">%{_javadir}</systemitem> rpm macro defines the main jar repository. Historically it was the sole directory used by the 1.0 JPackage distribution, before packaging constraints forced a more complex system. It usually expands into <filename class="directory">/usr/share/java</filename>.
        </para>

	<para>
All jar files and directories of jar files that do not depend on a particular Java standard version or JNI shall be installed in <filename class="directory">%{_javadir}</filename>.
        </para>

      </section>

      <section>
	<title><filename class="directory">/usr/share/java-ext</filename></title>

	<para>
From <systemitem class="macro">%{_javadir}</systemitem> we derive <filename class="directory">%{_javadir}-ext</filename>. All jar files and directories of jar files that depend on a particular Java standard version but not JNI shall be installed in <filename class="directory">%{_javadir}-ext</filename>.
        </para>

      </section>

      <section>
	<title><filename class="directory">/usr/share/java-x.y.z</filename></title>

	<para>
We also derive the <filename class="directory">%{_javadir}-x.y.z</filename> directories. They contain symlinks to files or directories of <filename class="directory">%{_javadir}-ext</filename> for all elements that are valid for the x.y.z Java standard version. Since an implementation is usually valid for a range of Java standard iterations, a file or directory in <filename class="directory">%{_javadir}-ext</filename> will usually have several symbolic links pointing to it. Also of note are the non-versioned symlinks : for two jars named <filename>foo13.jar</filename> and <filename>foo14.jar</filename>, the <filename class="symlink">foo.jar</filename> symlink will point to <filename>foo13.jar</filename> in <filename class="directory">%{_javadir}-1.3.0</filename> and <filename class="directory">%{_javadir}-1.3.1</filename>, and <filename>foo14.jar</filename> in <filename class="directory">%{_javadir}-1.4.0</filename>, <filename class="directory">%{_javadir}-1.4.1</filename> and <filename class="directory">%{_javadir}-1.4.2</filename>.
        </para>

	<para>
Unfortunately the Java standard has been known to change enough between minor versions that we must take into account the full version and distinguish between <filename class="directory">%{_javadir}-1.4.0</filename> and <filename class="directory">%{_javadir}-1.4.1</filename>.
        </para>

	<example>
	  <title>Java standard version-specific repositories usage</title>
	  <screen>
<filename class="directory">/usr/share/java-ext/jsse</filename>
<filename>/usr/share/java-ext/jsse/jcert-1.0.3.01.jar</filename>
<filename class="symlink">/usr/share/java-ext/jsse/jcert.jar</filename> &rarr; <filename>jcert-1.0.3.01.jar</filename>
<filename>/usr/share/java-ext/jsse/jnet-1.0.3.01.jar</filename>
<filename class="symlink">/usr/share/java-ext/jsse/jnet.jar</filename> &rarr; <filename>jnet-1.0.3.01.jar</filename>
<filename>/usr/share/java-ext/jsse/jsse-1.0.3.01.jar</filename>
<filename class="symlink">/usr/share/java-ext/jsse/jsse.jar</filename> &rarr; <filename>jsse-1.0.3.01.jar</filename>
<filename class="symlink">/usr/share/java-1.3.0/jsse</filename> &rarr; <filename class="directory">/usr/share/java-ext/jsse</filename>
<filename class="symlink">/usr/share/java-1.3.1/jsse</filename> &rarr; <filename class="directory">/usr/share/java-ext/jsse</filename>
            </screen>
	</example>

      </section>


      <section>
	<title><filename class="directory">/usr/share/java-utils</filename></title>

	<para>
We also derive <filename class="directory">%{_javadir}-utils</filename>. It is used to host java-related scripts and functions, including the main shell-script function library <filename>java-functions</filename>.
        </para>

      </section>

    </section>

    <section>
      <title><systemitem class="macro">%{_jnidir}</systemitem>:
 <filename class="directory">/usr/lib/java</filename></title>

      <para>
The <systemitem class="macro">%{_jnidir}</systemitem> rpm macro defines the main JNI jar repository. Like <systemitem class="macro">%{_javadir}</systemitem> it is declined in -ext and -x.y.z variants. It follows exactly the same rules as the <systemitem class="macro">%{_javadir}</systemitem>-derived tree structure, except that it hosts jars that use JNI.
      </para>

      <para>
<systemitem class="macro">%{_jnidir}</systemitem> usually expands into <filename class="directory">/usr/lib/java</filename>.
      </para>

    </section>

    <section>
      <title><systemitem class="macro">%{_jvmdir}</systemitem></title>

      <section>
	<title><filename class="directory">/usr/lib/jvm</filename></title>

	<para>
The <systemitem class="macro">%{_jvmdir}</systemitem> rpm macro defines the root directory under which the different system JVMs are installed. It usually expands into <filename class="directory">/usr/lib/jvm</filename>.
        </para>
      </section>

      <section>
	<title><filename class="directory">/usr/lib/jvm-ext</filename></title>

	<para>
From <systemitem class="macro">%{_jvmdir}</systemitem> we derive <filename class="directory">%{_jvmdir}-ext</filename>. Each subdirectory of <filename class="directory">%{_jvmdir}</filename> must have a twin in <filename class="directory">%{_jvmdir}-ext</filename>. It is used to register Java extensions bundled with the <acronym>SDK</acronym> or <acronym>RE</acronym> with symbolic links pointing inside the JVM structure in <filename class="directory">%{_jvmdir}</filename>.
        </para>

	<para>
The symbolic links shall point to the actual in-JVM jar file providing the extension (though that is not strictly necessary for the system to work), be available in versioned and non-versioned versions and follow general naming rules.
        </para>

      </section>

    </section>

    <section>
      <title><systemitem class="macro">%{_sysconfdir}</systemitem>/java:
 <filename class="directory">/etc/java</filename></title>

      <para>
<filename class="directory">%{_sysconfdir}/java</filename> hosts the general configuration files related to the java subsystem, mainly <filename>java.conf</filename>.
      </para>
    </section>

    <section>
      <title><systemitem class="macro">%{_javadocdir}</systemitem></title>

      <para>
This is the root of all installed javadoc documentation. It's location and intended usage are debated right now.
      </para>
    </section>

  </chapter>

  <chapter>
    <title>Scripts and actual run-time classpath resolution</title>

    <para>
We assume the correct environment variables have already been set, ie at least <envar>$JAVA_HOME</envar> to select a JVM in <filename class="directory">%{_jvmdir}</filename>, and eventually the relevant <envar>$JAVACMD</envar>, <envar>$LD_ASSUME_KERNEL</envar>, <envar>$LANG</envar>, and <envar>$JAVA_COMPILER</envar> variables.
    </para>

    <warning>
      <title>FIXME</title>

      <para>
The current implementation is not sane and carries a lot of legacy garbage. A clean implementation would be to read these values in <filename>~/.apprc</filename>, falling back on <filename>/etc/app.conf</filename>, the user environment, <filename>~/.java</filename> and <filename>/etc/java/java.conf</filename>. If <envar>$JAVA_HOME</envar> was still undefined then, use<filename>/usr/lib/jvm/java</filename> as default.
      </para>
      <para>
Unfortunately we are not doing so right now.
      </para>
    </warning>

    <section>
      <title>General resolution rules</title>

      <para>
When queried for <emphasis>foo/bar-x.y</emphasis> we search for the <filename>foo/bar-x.y.jar</filename> jar file, then the <filename class="directory">foo/bar-x.y</filename> jar directory in the following locations:
      </para>

      <itemizedlist>
	<listitem>
	  <formalpara>
	    <title><filename class="directory">%{_jvmdir}-ext/name</filename></title>
	    <para>
The shadow of the JVM defined by <envar>$JAVA_HOME</envar>=<filename class="directory">%{_jvmdir}/name</filename>. This is the JVM-specific repository where we register the Java extensions it includes.
            </para>
	  </formalpara>
	</listitem>
	<listitem>
	  <formalpara>
	    <title><filename class="directory">%{_jnidir}/java-version</filename></title>
	    <para>
Where <emphasis>java-version</emphasis> is the JVM standard Java compliance level as deduced from
<screen><prompt>[EMAIL PROTECTED] dir]$</prompt> <command>$JAVACMD</command> <option>-version</option></screen>
            </para>
	  </formalpara>
	</listitem>
	<listitem>
	  <formalpara>
	    <title><filename class="directory">%{_javadir}/java-version</filename></title>
	    <para>
The java-version specific non-JNI jar repository.
            </para>
	  </formalpara>
	</listitem>
	<listitem>
	  <formalpara>
	    <title><filename class="directory">%{_javadir}</filename></title>
	    <para>
The general jar repository.
            </para>
	  </formalpara>
	</listitem>
      </itemizedlist>

      <para>
If we didn't find anything, the search is repeated for <filename>foo/bar.jar</filename>, <filename class="directory">foo/bar</filename>, <filename>foo.jar</filename> then at last the <filename class="directory">foo</filename> directory. Note the scan is performed for jar/directory pairs ie a subdirectory located in a more specific repository will always have precedence on a jar with the same name located in a less specific repository.
      </para>

    </section>

    <section>
      <title><command>find-jar</command></title>

      <cmdsynopsis><command>find-jar</command><arg choice ="req">element</arg></cmdsynopsis>

      <para>
The <command>find-classpath</command> command tests the resolution of a given element. If successful it will return a jar file or a directory. It is solely intended for testing resolution and should not be used in scripts. Even for single-element classpath building the following command is preferred, since single-element searches can produce multiple file results when resolving into a directory.
      </para>

    </section>

    <section>
      <title><command>build-classpath</command></title>

      <cmdsynopsis><command>build-classpath</command><arg choice ="req" rep="repeat">element</arg></cmdsynopsis>

      <para>
The <command>build-classpath</command> command builds a standard classpath following the general resolution rules. It takes a list of elements as arguments. If an element resolves in a directory, all its children jar files are included in the classpath.
      </para>

      <para>
Like the following command it will fail, return an non-zero error code and write to the error console if one or more of the requested elements were not found. Therefore for a classpath composed of required and optional parts recommended building practice is the following:
     </para>
     <informalexample>
	<programlisting>
CLASSPATH=$(build-classpath list_of_required_elements):$(build-classpath list_of_optional_elements 2> /dev/null)
        </programlisting>
      </informalexample>

    </section>

    <section>
      <title><command>build-jar-repository</command></title>

      <cmdsynopsis><command>build-jar-repository</command> <arg choice ="req">directory</arg> <arg choice ="req" rep="repeat">element</arg></cmdsynopsis>

      <para>
The <command>build-jar-repository</command> command constructs a flat directory of jar file symlinks following the same rules. It takes a directory name followed by a list of elements as arguments. It will try to create a <filename class="symlink">[foo][bar]xxx.jar</filename> set of symbolic links in the target directory for each <emphasis>foo/bar</emphasis> requested element<footnote>
	  <para>
Remember, a single element can resolve in a full directory of jar files.
          </para>
	</footnote>. The special symlink naming makes it possible to recognize they were created by this command and is required for the following command.
      </para>

      <para>
<command>build-jar-repository</command> can be safely used on the same directory several times. Previous symlinks won't be removed. If one wants to reset the directory the symbolic links must be cleaned up manually.
      </para>

    </section>

    <section>
      <title><command>rebuild-jar-repository</command></title>

      <cmdsynopsis><command>rebuild-jar-repository</command> <arg choice ="req">directory</arg></cmdsynopsis>

      <para>
The <command>rebuild-jar-repository</command> command refreshes a jar repository created with <command>build-jar-repository</command>. It takes the directory name as argument. It is intended to be run after <envar>$JAVA_HOME</envar> was changed to insure all symlinked jar files are still compatible with the new JVM.
      </para>

    </section>

  </chapter>
</book>

Attachment: signature.asc
Description: Ceci est une partie de message =?ISO-8859-1?Q?num=E9riquement?= =?ISO-8859-1?Q?_sign=E9e?=

Reply via email to