Handling of basic build steps in Java
* javac
* usage of build-claspath, build-jar-repository to prepare for build
* ...

=== add_maven_depmap macro

Maven identifies JAR files by a set of strings: groupId, artifactId and version
(mostly). To let XMvn know what groupId:artifactId corresponds to which
POM or JAR file, we may use the `%add_maven_depmap` macro. However, if package
is build in standard way (i.e.: `%mvn_build` and `%mvn_install`), then calling
`%add_maven_depmap` is neither needed nor recommended.  This macro is usually
useful only for packages that use other build tool than Maven (e.g.: ant,
gradle).  It creates files in `%{_mavendepmapfragdir}` that map
groupId:artifactId pairs to JAR files under `%{_javadir}`. These files are
called depmap fragments. The macro can read the groupId and artifactId from the
POM file or maintainer can pass this information as an argument.  All fragments
in `%{_mavendepmapfragdir}` directory are read by XMvn, allowing the
locally installed JAR and POM files to be used as a maven repository.

Note that -- unless you use the `-f` option as shown below -- all
depmap fragments for a given package are written to the same file,
`%{_mavendepmapfragdir}/%{name}`. You should be sure to include this
file in the `%files` section of your RPM.

For the macro to work properly, all JAR files must be copied into `%{_javadir}`
and all POM files must be copied into `%{_mavenpomdir}` and given file names of
the following form, where `jarname` is the name of the JAR without the .jar
suffix:

[source,spec]
--------
%{_mavenpomdir}/JPP[.subdirectory]-jarname.pom
--------

Note that the subdirectory is only necessary if the JAR file is put into a
subdirectory of `%{_javadir}`. For example:

* For junit, the JAR is `%{_javadir}/junit.jar`, so the POM would be
  `%{_mavenpomdir}/JPP-junit.pom`.
* For plexus-ant-factory, the JAR is `%{_javadir}/plexus/ant-factory.jar`, so
  the POM would named `%{_mavenpomdir}/JPP.plexus-ant-factory.pom`.

If a POM is installed with no corresponding JAR file -- for example, for parent
POM files -- the same convention should be followed:

* The Apache commons parent POM is installed in
  `%{_mavenpomdir}/JPP-commons-parent.pom`.

In its simplest form (a POM without a JAR file), `%add_maven_depmap` looks like
this:

.Parent POM
[source,spec]
--------
%add_maven_depmap JPP-%{name}.pom
--------

This will read the POM file in question and provide a mapping between the
groupId and artifactId inside the POM file and the POM file placed into
`%{_mavenpomdir}`.

For a POM that maps directly to a JAR file, the following is the correct form:

.Standard invocation
[source,spec]
--------
%add_maven_depmap JPP-%{name}.pom %{name}.jar
--------

In addition to creating the POM mapping, this will also ensure that the correct
JAR is associated with the groupId and artifactId from the POM.

Even if there is no POM file from some reason, it is still possilbe to generate
mapping between Maven artifact and corresponding JAR file:

[source,spec]
--------
%add_maven_depmap groupId:artifactId[:extension[:classifier]]:version %{name}.jar
--------

.Providing additional artifact mappings
[source,spec]
--------
%add_maven_depmap JPP-%{name}.pom %{name}.jar -a "org.apache.commons:commons-lang"
--------
This form also adds additional mappings for given POM/JAR file. For example, if
the POM file indicates that it contains groupId commons-lang, artifactId
commons-lang, this form ensures that we also add a mapping between groupId
org.apache.commons and the installed POM/JAR files. This is necessary in cases
where the groupId or artifactId may have changed, and other packages might
require different IDs than those reflected in the installed POM.

.Multiple subpackages
[source,spec]
--------
%add_maven_depmap JPP-%{name}.pom %{name}.jar -f "XXX"
--------
This form stores dependency mapping inside `%{_mavendepmapfragdir}/%{name}-XXX`
instead of standard location. This is useful for packages with multiple
subpackages where each has its own JAR files.

.Multiple artifacts in a subdirectory
[source,spec]
--------
%add_maven_depmap JPP.%{name}-sub.pom %{name}/sub.jar
--------

This form should be used when a package consists of multiple JAR files that are
installed into a subdirectory of `%{_javadir}`. Note that in this case, the POM
file name includes the optional subdirectory field.


=== Generating Application Shell Scripts
As mentioned in section about xref:XFor_Packagers[Java packaging basics], all
Java applications need wrapper shell scripts to setup the environment before
running JVM and associated Java code.


The jpackage-utils package contains a convenience `%jpackage_script` macro that
can be used to create scripts that work for the majority of packages.  See its
definition and documentation in `/etc/rpm/macros.jpackage`.  One thing to pay
attention to is the 6th argument to it - whether to prefer a JRE over a full SDK
when looking up a JVM to invoke - most packages that don't require the full Java
SDK will want to set that to `true` to avoid unexpected results when looking up
a JVM when some of the installed JRE's don't have the corresponding SDK (*-devel
package) installed.

[source,spec]
--------
%install
...
%jpackage_script msv.textui.Driver "" "" msv-msv:msv-xsdlib:relaxngDatatype:isorelax msv true
...
--------

The previous example installs the "msv" script (5th argument) with main class
being msv.textui.Driver (1st argument). No optional flags (2nd argument) or
options (3rd argument) are used. This script will add several libraries to
classpath before executing main class (4th argument, JAR files separated with
":"). `build-classpath` is run on every part of 4th argument to create full
classpaths.

=== Replacing JARs with symlinks using xmvn-subst

Sometimes it may be needed to replace all JAR files in current directory with
symlinks to the system JARs located in `%{_javadir}`. This task can be achieved
using tool called `xmvn-subst`.

[source,shell]
--------
$ ls -l
-rw-r--r--. 1 msrb msrb  40817 Oct 22 09:16 cli.jar
-rw-r--r--. 1 msrb msrb 289983 Oct 22 09:17 junit4.jar
-rw-r--r--. 1 msrb msrb 474276 Oct 22 09:14 log4j.jar
$ xmvn-subst .
[INFO] Linked ./cli.jar to /usr/share/java/commons-cli.jar
[INFO] Linked ./log4j.jar to /usr/share/java/log4j.jar
[INFO] Linked ./junit4.jar to /usr/share/java/junit.jar
$ ls -la
lrwxrwxrwx. 1 msrb msrb   22 Oct 22 10:08 cli.jar -> /usr/share/java/commons-cli.jar
lrwxrwxrwx. 1 msrb msrb   22 Oct 22 10:08 junit4.jar -> /usr/share/java/junit.jar
lrwxrwxrwx. 1 msrb msrb   22 Oct 22 10:08 log4j.jar -> /usr/share/java/log4j.jar
--------

The example above shows how easy the symlinking can be. However, there are some
limitations. Original JAR files need to carry metadata which tell xmvn-subst
for what artifact given file should be substituted. Otherwise `xmvn-subst` won't
be able to identify the Maven artifact from JAR file.

[TIP]
======
See `xmvn-subst -h` for all available options.
======
