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
Attachment:
signature.asc
Description: This is a digitally signed message part