Hmm. Sounds interesting. I had a look at
org.apache.tools.ant.taskdefs.Manifest to see what I could see.
-- A Manifest object contains a set of Section object keyed by name
-- A Section contains a set of Attribute objects, keyed by
name.toLowerCase().
-- Both mappings use java.util.Hashtable to maintain the String:Object
mappings.
There is no code that I could see which sorts the attributes in a section
upon writing, so the order will be that imposed by the hashCode values of
the keys. Indeed, running the simple test program test.java:
import java.util.*;
class test {
public static void main(String[] args) {
Hashtable h = new Hashtable();
addEntry(h, "Main-Class");
addEntry(h, "Created-By");
addEntry(h, "Class-Path");
int i = 0;
for (Enumeration e = h.elements(); e.hasMoreElements();) {
System.out.println(String.valueOf(i++) + ": " +
e.nextElement());
}
printHash("Main-Class");
printHash("Created-By");
printHash("Class-Path");
printHash("main-class");
printHash("created-by");
printHash("class-path");
}
private static void printHash(String s) {
System.out.println(s + ": " + s.hashCode());
}
private static void addEntry(Hashtable h, String s) {
s = s.toLowerCase();
h.put(s, s);
}
}
Yields the following results:
0: main-class
1: created-by
2: class-path
Main-Class: 1325056100
Created-By: -931871332
Class-Path: 1655920538
main-class: -638856092
created-by: 1369632092
class-path: -336591014
Therefore, the test class printed the elements of the hashtable [0, 1, 2] in
the same order seen by you when the manifest is written to a file, which
also explains why the order of the XML does not matter.
I think I remember reading somewhere about the Class-Path that it *must* be
the line directly following the Manifest-Version string. Definitely my past
experience with .ear's deployed within Weblogic and JBoss suggest it.
Unfortunately I cannot seem to find any documentation that confirms this.
If that is the case, I would consider this to be a bug in Manifest.java
since it does not enforce this ordering.
The fix to Manifest.java would be to check if the attribute "class-path"
exists, and write this first.
The source for ant 1.4.1 has this 'bug' (if it is one) as well as the cvs
tip.
The workaround would seem to be <exec> jar directly from within ant, it
would appear that <jar> would be unusable for you under these conditions.
Can anyone confirm that Class-Path needs to be the first entry in the main
section of a manifest?
Cheers,
Paul
> -----Original Message-----
> From: Todd Wilson [mailto:[EMAIL PROTECTED]]
> Sent: Tuesday, March 12, 2002 1:20 PM
> To: [EMAIL PROTECTED]
> Subject: Using Main-Class and Class-Path in a manifest file
>
>
> Greetings,
>
> We're attempting to use Ant in generating a JAR file that creates a
> manifest file which uses both the Class-Path and Main-Class
> properties,
> but can't seem to be able to get it to work.
>
> Here is some information that would be useful to any wanting
> to respond--
>
>
> ====================================================
> Our directory structure:
> ====================================================
> ant_test
> '- build
> '- lib
> '- log4j.jar
> '- build.xml
> '- dist
> '- src
> '- HelloWorld.java
> ====================================================
>
>
> ====================================================
> Our build.xml file:
> ====================================================
> <project name="HelloWorld" default="dist" basedir=".">
>
> <target name="init">
> <!-- set global properties for this build -->
> <property name="src" value="src"/>
> <property name="build" value="build"/>
> <property name="dist" value="dist"/>
>
> <!-- Create the time stamp -->
> <tstamp/>
> <!-- Create the build directory structure used by compile -->
> <mkdir dir="${build}"/>
> </target>
>
> <target name="compile" depends="init">
> <!-- Compile the java code from ${src} into ${build} -->
> <javac srcdir="${src}" destdir="${build}"/>
> </target>
>
> <target name="dist" depends="compile">
> <!-- Create the distribution directory -->
> <mkdir dir="${dist}"/>
>
> <!-- Put everything in ${build} into the HelloWorld.jar file -->
> <jar jarfile="${dist}/HelloWorld.jar" basedir="${build}">
> <manifest>
> <attribute name="Class-Path" value=". ./lib/log4j.jar"/>
> <attribute name="Main-Class" value="HelloWorld"/>
> </manifest>
> </jar>
> </target>
>
> <target name="clean">
> <!-- Delete the ${build} and ${dist} directory trees -->
> <delete dir="${build}"/>
> <delete dir="${dist}"/>
> </target>
> </project>
> ====================================================
>
>
> ====================================================
> HelloWorld.java:
> ====================================================
> import org.apache.log4j.*;
>
> public class HelloWorld
> {
> public static Category log = Category.getInstance(
> HelloWorld.class.getName() );
>
> public HelloWorld()
> {
> System.out.println( "Hello world!" );
>
> log.debug( "Log4J is working." );
> }
>
> public static void main( String args[] )
> {
> BasicConfigurator.configure();
>
> HelloWorld hw = new HelloWorld();
> }
> }
> ====================================================
>
>
> When we run ant in the "ant_test" directory it produces the
> HelloWorld.jar file in the "dist" directory as it's supposed to, but
> running the jar with
>
> java -jar HellowWorld.jar
>
> produces the following error message:
>
> Exception in thread "main" java.lang.NoClassDefFoundError:
> org/apache/log4j/Category
> at HelloWorld.<clinit>(Unknown Source)
>
> So it's apparently finding our "Main-Class" just fine, but
> seems to be
> ignoring the "Class-Path" property.
>
> If we unjar the HelloWorld.jar file it reveals that the following
> manifest file was generated by Ant:
>
> ====================================================
> Manifest-Version: 1.0
> Main-Class: HelloWorld
> Created-By: Ant 1.4.1
> Class-Path: . ./lib/log4j.jar
> ====================================================
>
> In an attempt to diagnose the problem, we then copy the
> contents of the
> build directory (which contains the HelloWorld.class file
> generated when
> Ant ran as well as the lib directory containing log4j.jar) into a
> separate tmp directory. We then attempt to jar up the
> contents of tmp
> using the manifest file created by Ant, with the following command:
>
> jar -cfm HelloWorld.jar ../dist/META-INF/MANIFEST.MF ./*
>
> Again, notice that we're designating the manifest file that was
> generated by Ant as the manifest file that should be used for
> the newly
> created HelloWorld.jar file. After running this jar command
> we attempt
> to run the second HelloWorld.jar file with
>
> java -jar HelloWorld.jar
>
> and it runs just fine. If we unjar this second
> HelloWorld.jar file we
> find that the contents of it are identical to that of the first
> HelloWorld.jar file (as near as we can tell) aside from the manifest
> file which now looks like this:
>
> ====================================================
> Manifest-Version: 1.0
> Created-By: Ant 1.4.1
> Class-Path: . ./lib/log4j.jar
> Main-Class: HelloWorld
> ====================================================
>
> Running diff on the two files reveals that, aside from white
> space, the
> only difference between the two is that the "Main-Class" line in the
> first manifest file is on the second line where the
> "Main-Class" line in
> the second manifest file is on the last line. It seems odd that the
> order in which the properties appear in the manifest file
> would make any
> difference, but, as I mentioned, that's the only discrepancy we could
> find between the two jars.
>
> It's as though the java runtime parses through the manifest file and,
> upon reaching the "Main-Class" line, immediately invokes the class
> designated rather than parsing the rest of the file in order
> to set the
> classpath first. If this is the case, is there any way to
> make Ant put
> the "Main-Class" property at the end of the manifest file?
> Rearranging
> the XML tags doesn't seem to have any affect on this.
>
> We've also tried creating a manifest file before running Ant that
> positions the "Main-Class" property at the end, then using the
> "manifest" attribute of the "jar" tag, but when Ant runs it moves the
> "Main-Class" property up to the second position, as before.
>
> We've tried this process on Linux running JDK 1.4 as well as Win2K
> running JDK 1.3.1_01, and have gotten the same results. The
> log4j.jar
> file can be obtained from http://jakarta.apache.org/log4j/,
> but I'm sure
> you all already knew that :)
>
> Sorry this message is so long-winded, but I figure it's better to be
> verbose in situations like this rather than terse. Many thanks in
> advance to anyone willing to lend a hand.
>
> Regards,
>
> Todd Wilson
>
> P.S. Lest we be accused otherwise, we've already spent a
> fair amount of
> time searching the archives of the list for a solution to
> this problem,
> but, unfortunately, haven't been successful.
>
>
> --
> To unsubscribe, e-mail:
<mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>