[fedora-java] Re: [JPackage-discuss] XSLT limitations (was: Re: Recursive Classpath Thing)

Nicolas Mailhot Nicolas.Mailhot at laPoste.net
Mon Mar 14 19:13:07 UTC 2005


Le lundi 14 mars 2005 à 16:09 +0000, Gary Benson a écrit :

> Before I jump in feet first, can I clarify what the ultimate goal is.
> As far as I see it, currently the command "build-classpath bcel" will
> print out "/usr/share/java/bcel.jar".  You would like it to print out
> "/usr/share/java/regexp.jar:/usr/share/java/bcel.jar".  Am I correct?

Ok, you asked it you'll get it;) CC-ing fedora-devel-java, Steve Cohen
(who also expressed some interest lately) and the common java packaging
list (since I do believe this is larger than JPackage alone and is
cojapas material at least).

The ultimate goal as you write is to generate a
classic /usr/share/java/regexp.jar:/usr/share/java/bcel.jar classpath
(or populate a directory with jar symlinks, those being the two main
ways an application creates its own classpath). A lot of people me
included feel you can't create classpathes like this from the jar files
alone, and you need additional metadata, probably in standalone files
like is already the case for various Unix systems. There is broad
agreement on what those files should contain.

A lesser number of people want these standalone files to be in XML. I'm
among this group, mainly because we will have to deal with windows users
at some point and I don't even want to deal with problems like CRLF in
2005.

I'll describe now broadly what I personally think these XML files
contents should be. The thing that converts these files to the
aforementioned path is left to your discretion. Like you rightly wrote,
once such an engine is written and proves the validity of the approach
it can be rewritten in other langages. The main thing is not to have to
rewrite all the description files all the times, and keep the output
stable so startup scripts do not need rewriting either.

1. a single XML file should describe one classpath unit provided by a
given project.

2. a classpath unit is most of the times a jar file or a set of jar
files. But it is not always the case : it can also contain stuff like
property files, xml files, even sometimes resources like sound files,
icons, etc

3. on some platforms all those files are lumped in a single per-app dir.
On others like Linux common conventions like the FHS mandate separation
of configuration and data parts

4. likewise on multi-user systems separate users must be able to
overload the configuration parts transparently

5. lastly while the configuration of an infrastructure is often
system-wide in scope, sometimes it's very useful to be able to overload
it on a per-app basis (a common example would be log4j - you don't want
all the apps in the system share the same log files, even if you want
them to share the log4j code)

6. therefore while a classpath unit descriptor should list the files
that compose it, exact file location should be left to separate policy
files (for example given a set of files search the jars
in /usr/share/java, the .properties in the same dir then ~/.java
then /etc/java, etc)

7. when a classpath unit is an implementation of a common java
infrastructure like jmx it should declare it

8. this means the possibility of simultaneous installations of several
implementations of the same thing on a given system exists. While some
objective factors like jvm compatibility (I'll get to this point later)
can be used to choose a particular implementations, sometimes you'll
just have several valid choices. It is probably very dangerous to let
classpath units self-declare their relative priorities (everyone would
want to be king). Therefore we need separate policy files that list
implementation priorities (probably distro specific, maybe overloadable
by the user, should list all known implementations to be effective and
the system then should choose between the implementations actually
present)

9. a particular classpath unit must list all the other classpath units
it depends on. Some of them might be mandatory (won't work without them)
others might be opportunistic (use them if they're here, if not the app
will still work without them)

10. a particular classpath unit might use jni and require a particular
library to be in the app library path (now since we've already decided
to output a java classpath, I don't know if it's better to do such
resolution in a separate utility that takes a classpath in input and
outputs a LD_LIBRARY_PATH, if you use the same command to output one of
them depending on a CLI parameter or if you always output two lines, one
with the classpath the other with the LD_LIBRARY_PATH. And apps like
tomcat that want directories of jars are yet another problem)

11. a particular classpath unit might use some features of the java
langage only found on some java language versions and require the jvm to
support them

12. a particular classpath unit might work with some jvms only - the
extreme case being in-jvm implementations that only work with a single
jvm (yes I think in-jvm libraries need to be covered by the xml
descriptors too)

13 sometimes you may need to generate your classpath in separate bits
(for example an ant build.xml where some targets require additional jars
like junit - they'll need their path in pieces but the pieces must be
compatible with each other)

14 sometimes a classpath unit has a direct influence on some othe jvm
parameters like memory sizing

15 you need to handle classpath unit versionning- given the problem
scope managing version ranges is probably best.

16 lots of other considerations that are eluding me right now but will
come to light later. The main point is classpath building is _hard_,
this is largely hidden by the fact classpathes are by and large manually
written right now, but if we want to automate this we must remember it.
When writing a classpath builder you have to remember you may need to
add some rules later, so under-specifying is probably a bad idea.

Given all this the xml files I started working on looked like this :

<?xml version="1.0"?>
<pathelem name="foo" version="a.b.c">

  <config file="foo/fooconf"/>
  <config file="/usr/share/xml/foo/foo" ext="xml"/>
  <config dir="/usr/share/foo-common" version="v.w.x"/>
  <config dir="/usr/share/foo"/>
  <classes file="foo-core"/>
  <classes file="foo-lib"/>
  <classes file="foo-contrib" ext="zip" version="d.e.f"/>
  <classes libdir="/usr/share/foo/lib" version=""/>

  <depends>
    <pathelem name="barA"/>
    <pathelem name="barB" version="d.e.f"/>
    <pathelem name="barC" minver="d.e.f" maxver="x.y.z"/>
  </depends>

  <conflicts>
   <java minver="1.5.0"/>
   <jvm name="java-ibm" maxver="1.3.1"/>
   <pathelem name="toto" version="x.y.y"/>
  </conflicts>

  <implements>
   <pathelem name="bob"/>
   <pathelem name="bill" minver="e.r.t"/>
  </implements>

  <native>
   <dir name="/usr/lib/java"/>
   <dir name="/opt/oracle/oracle-x-y-z/lib"/>
  </native>

</pathelem>

And this :

<?xml version="1.0"?>
<!-- Java policy setup:
     - paths to use in priority order
     - virtual weights ?
     -->
<policy>

 <config path="~/.system/etc/java"/>
 <config path="~/.java/etc"/>
 <config path="/etc/java"/>

 <classes path="~/.system/share/java"/>
 <classes path="~/.java/lib"/>
 <classes path="/usr/share/java"/>

</policy>

The exact element hierarchy can be probably hammered on while writing
the actual implementation. As long as all the elements are present in
the files mass syntax changing can be handled by xslt later.

I hope I haven't disgusted you and you still want to work on the
problem. If you still have questions don't hesitate to ask. For now I'm
closing this post before writing a novel.

Regards,

-- 
Nicolas Mailhot
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: This is a digitally signed message part
URL: <http://listman.redhat.com/archives/fedora-devel-java-list/attachments/20050314/ad7e11c2/attachment.sig>


More information about the fedora-devel-java-list mailing list