How can I extract a file from a classpath? - java

I want to add a file to a classpath from a fileset. How can I do this with Ant?
For example, let's say the fileset with id "my.fileset" contains:
dir1/subdir1/file1.jar, dir2/subdir2/file2.jar, dir3/subdir3/file3.jar
I know the name of the jar: "file2.jar". Now, I want to find the full filename and add it to a classpath (I assume this will require to use a regex like ".*file2.*)

I'm not sure I understand the question. Are you trying to dynamically add the file to the classpath, or are you trying to set a classpath in ant? In ant, once you set a property (like a classpath), you cannot change it.
To create a classpath in a normal build.xml do something like this:
<path id="compile.classpath">
<pathelement location="${foo.jar}"/>
<fileset dir="./bin">
<include name="*.jar"/>
</fileset>
<pathelement location="./lib"/>
<fileset dir="./lib">
<include name="**/*.jar"/>
</fileset>
</path>
This will add directories, or every jar in a bin folder, or even every jar in the ./lib sub-tree.

Related

Splash-Screen works in IDE but not as .jar - issue with ANT?

I'm attempting to add a splash-screen to a large Java project. The application is compiled into an executable .jar file using ANT.
I am able to get the splash screen working easily from NetBeans by simply adding -splash:src/com/.../.../image.PNG to my main project's VM options. However, adding SplashScreen-Image: com/.../.../image.PNG to my manifest file fails with "SplashScreen.getSplashScreen() returned null"
I have already opened up my .jar archive to confirm that things were set up correctly: my META-INF\MANIFEST.MF file includes the SplashScreen-Image line. I have tried moving it before or after Main-Class. My actual image.PNG is also in the archive, in the correct path location.
I compile this java project with ANT, which I can guess is the source of my problems (I was able to make a simple, "jar cmf ..." example work just fine).
I use the following to get the project elements ready for achiving:
<target name="compile" depends="init"
description="Compile the source">
<!-- Compile the java code from ${src} into ${build} -->
<path id="lib.path.ref">
<fileset dir="${path_to_jre}" includes="*.jar"/>
</path>
<javac srcdir="${src}" destdir="${build}" source="${java_ver}" target="${java_ver}"
includeantruntime="false">
<!--compilerarg value="-Xbootclasspath/p:${toString:lib.path.ref}" compiler="javac1.7"/-->
<compilerarg value="-Xlint:unchecked"/>
<classpath>
<fileset dir="${LibDir}">
<include name="*.jar"/>
</fileset>
<pathelement path="${dependant_jar}"/>
<pathelement path="${another_dependant_jar}"/>
</classpath>
</javac>
<!-- Copy the .png files -->
<copy todir="${build}">
<fileset dir="${src}" casesensitive="false">
<include name="**/*.PNG"/>
</fileset>
</copy>
</target>
Notice that I use a copy to move .PNG files in with .class files. My image.PNG for the Splash Screen is just in with the others. I added it to my netbeans project by simply copying it there - nothing fancy.
My achieve target is as follows:
<target name="archive" depends="compile"
description="Generate the .jar file">
<!-- Put everything in ${build} into the .jar file -->
<jar jarfile="${jarfile}" basedir="${build}">
<!-- Merge in contents of dependency .jars -->
<zipfileset src="${LibDir}/snakeyaml.jar"/>
<zipfileset src="${dependant_jar}"/>
<zipfileset src="${another_dependant_jar}"/>
<!-- Specify main class in manifest -->
<manifest>
<attribute name="SplashScreen-Image" value="com/../../image.PNG"/>
<attribute name="Main-Class" value="${mainclass}"/>
</manifest>
</jar>
</target>
So my manifest in the eventual .jar is created here, which is also where I eventually realized to add the splashscreen tag.
I am somewhat new to working with ANT, so any advice regarding how to handle this or what to look for is appreciated.
It is not an issue with Ant. The problem is that the -splash option takes a file name, but the SplashScreen-Image manifest attribute must refer to a jar entry. If com/example/brian/image.PNG isn’t in the .jar file, it won’t be usable by SplashScreen-Image. The purpose of a .jar file is to be act as a self-contained module or application, so it should include all of the resources it needs.
The solution is to include the image in your .jar file:
<jar jarfile="${jarfile}" basedir="${build}">
<fileset dir="${src}" includes="**/*.PNG"/>
Update: Your build file was already adding the images to the .jar with a <copy> task, and I failed to notice it.
I have a solution, although I'm sure someone else will understand this better than I do.
I was able to run, with a splash-screen, using the Java binary in ../jre/lib/Java.exe, however I had initially been working from ../lib/Java.exe.
Looks like this is a known bug? Link here: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=7129420. I guess the path to the SplashScreen dll is hardcoded.
Note: Thanks to user VGR for the exhaustive help.

How to include external class files during build in ant

I have a package(with some outdated Java files) which i need to build using ant tool. I have some updated classes for which source is not available. So, I need to add the updated class to the jar during build and skip the outdated Java files from the build. Please let me know how to achieve this.
For example - I dont have the updated source java file for com.org.auth.ABC.Java, but i have the updated class file which i got from the another source ie com.org.auth.ABC.class. During build i need to point to the updated class(com.org.auth.ABC.class) for this class alone and create a new jar.
Please find how i am currently pointing to the class files below.
<target name="xxx.jar" depends="xjc,compile">
<jar destfile="${dist.dir}/xxx.jar">
<fileset dir="${classes.dir}" includes="**/*.class"/>
<fileset dir="${jaxb-classes.dir}" includes="**/*.class"/>
<fileset dir="${jaxb-source.dir}" includes="**/bgm.ser,**/jaxb.properties"/>
</jar>
</target>
If you want to leave some package from compilation you can use excludes attribute of fileset ant tag.
for example:
<fileset dir="src/">
<exclude name="**/dir_name_to_exclude/**" />
</fileset>
In order to include the specified class in compilation you can put the containing folder in your class-path using ant.
<path id="project.class.path">
<pathelement location="lib/"/>
<pathelement path="${java.class.path}/"/>
<pathelement path="path to your class file's base folder"/>
</path>
<javac srcdir="${src.dir}"
destdir="${classes.dir}"
classpathref="project.class.path">
... put source files here..
</javac>
And if you want to include that class-file in your jar then add it to fileset using include tag:
<fileset dir="classfiles">
<include name="your class file name"/>
</fileset>
Hope this helps

Need an ANT task to include a set of jar files in the final jar's /lib dir

My project folder has a bunch of dependent jars in:
/lib/someapi-1.1.1/main.jar
/lib/someotherapi-2.2.2/api-2.2.2.jar
/lib/...
I build a JAR file and my application requires that the dependent jars get included in the final jar in the /lib folder within the jar, so the final jar should have a structure something like:
/org/me/myclasses.class
/lib/main.jar
/lib/api-2.2.2.jar
How do I get the /lib/*.jar files flattened an included in the /lib directory of my final jar file?
CLARIFICATION
I'm essentially just trying to get a set of resource files flattened and added to a given directory in my final jar.
In case you wanted do skip the copy step, you could do it this way. It uses <mappedresources> to flatten from the source lib directories to the classes/lib area.
<jar destfile="${dist}/MyOneBigJar.jar">
<fileset dir="${classes}"/>
<mappedresources>
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
<chainedmapper>
<flattenmapper />
<globmapper from="*" to="classes/lib/*" />
</chainedmapper>
</mappedresources>
</jar>
The easiest way I see is to copy allyour jars to a temporary folder using the copy task and its flatten attribute, and to include the jars of this temporary directory into the destination jar.
ADDED DETAIL added by asker
Here's what the final ANT target looks like (for future reference):
<target name="dist">
<mkdir dir="${classes}/lib"/>
<copy flatten="true" todir="${classes}/lib" includeemptydirs="false">
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</copy>
<jar destfile="${dist}/MyOneBigJar.jar">
<fileset dir="${classes}"/>
</jar>
</target>

Apache ANT manifest classpath literal

I have an ANT build that compiles my Java project and builds a jar. An ANT target creates a manifest classpath for the jar. Everything works great.
Now, I would like to add a period '.' to the beginning of the manifest classpath so that the runtime working directory is on the classpath. How do I do that using manifestclasspath?
My manifestclasspath example:
<manifestclasspath property="foobar.manifest.classpath" jarfile="whocares.jar">
<classpath >
<pathelement path="."/>
<!-- :-( adds the working directory of the build. -->
<pathelement location="lib/some.jar"/>
<pathelement location="lib/someother.jar"/>
<fileset dir="${foobar.lib.dir}">
<include name="**/*.jar" />
</fileset>
</classpath>
</manifestclasspath>
<pathelement path="."/>adds the working directory of the build to my manifest classpath which is not what I want. I just want a period.
This is what I want the jar classpath to look like:
Class-Path: . lib/some.jar lib/someother.jar lib/blah.blah.blah.blah.b
lah.blah.jar /lib/and-on-and-on.jar
The key thing being the '.' as the first item in the classpath.
How to I make ANT add the literal '.' to the manifest class path?
Couldn't you just prepend manually :
<property name="theRealManifestClasspath" value=". ${foobar.manifest.classpath}"/>

Creating a config list of classpath jars in ant

I have a list of jars in an ant task like this..
<path id="lib.path.id">
<fileset dir="${lib.dir}">
<include name="jar/*.jar"/>
</fileset>
</path>
I want to unroll this into a config file like this..
wrapper.java.classpath.1=../lib/activation.jar
wrapper.java.classpath.2=../lib/bcel.jar
wrapper.java.classpath.3=../lib/c3p0-0.8.4.5.jar
wrapper.java.classpath.4=../lib/cglib-full-2.0.2.jar
....
How can I do this in ant?
As explained in my comment, if you are using Tanuki Service Wrapper for Java, you are not forced to list all your jar in the wrapper.conf, you can simply indicate a path that contains all your JAR files:
wrapper.java.classpath.1=/path/to/lib/*.jar
wrapper.java.classpath.2=/any/other/lib/directory/*.jar
wrapper.java.classpath.3=/a/path/to/one/library/my-library.jar
...
In Ant you can use the pathconvert task in order to convert the path collection to a String. Then you can use it in your config file. It won't be in the exact format you specified, but it will be in a proper classpath format, ready to use for a java command.
<pathconvert targetos="unix" property="wrapper.java.classpath" refid="lib.path.id"/>
To create a properties file use the propertyfile task:
<propertyfile file="my.properties">
<entry key="wrapper.java.classpath" value="${wrapper.java.classpath}"/>
</propertyfile>
Eran hinted the right direction. I am using the ant.library.dir as an example.
<project name="util">
<property name="lib.dir" value="${ant.library.dir}"/>
<target name="gen-property-file" description="">
<path id="lib.path.id">
<fileset dir="${lib.dir}">
<include name="*.jar"/>
</fileset>
</path>
<pathconvert pathsep="${line.separator}wrapper.java.classpath.Number="
property="echo.path.compile"
refid="lib.path.id">
</pathconvert>
<echo file="my.properties">wrapper.java.classpath.Number=${echo.path.compile}</echo>
</target>
This snippet procudes an file my.properties:
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-antlr.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-apache-bcel.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-apache-bsf.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-apache-log4j.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-apache-oro.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32\eclipse\plugins\org.apache.ant_1.7.1.v20100518-1145\lib\ant-apache-regexp.jar
wrapper.java.classpath.Number=D:\Programme\eclipse-rcp-helios-SR1-win32
...
You can replace the .Number and the Basepath manually or with a script.

Categories