ANT: Force error on missing resource? - ant

I've inherited an Ant build system that contains many resource
set definitions like this:
<files id="app1.lib.jars">
<include name="${java}/jre/lib/jsse.jar"/>
<include name="${work.lib}/jtidy.jar"/>
...
</files>
<files id="app2.lib.jars">
<include name="${work.lib}/itext.jar"/>
<include name="${work.lib}/commons-httpclient.jar"/>
...
</files>
<files id="app3.lib.jars">
<include name="${work.lib}/jdom.jar"/>
<include name="${ant.lib}/ant.jar"/>
...
</files>
There are perhaps a dozen of these, and each can contain anywhere from
5 to 50 files. The problem is that I'm reworking this system to use
Ivy for dependency management, and in the process some of the
references now point to non-existent files. Unfortunately, Ant does
not provide any help finding these bad pointers. When these resource
collections are used to define a classpath any <include...> tags
pointing to missing files are silently ignored.
I thought I could force an error by using the collections as the
source of a <copy...>, but even with failonerror="true" it just
ignored the bad references.
The command-line -v (verbose) and -d (debug) option didn't help
either. The output acknowledged that some were missing but didn't
actually show them
[echo] app1.lib.jars
[copy] C:\dev\src\tomcat6\work\java\jre\lib\jsse.jar omitted as C:\dev\src\tomcat6\work\verify\jsse.jar is up to date.
[copy] C:\dev\src\tomcat6\work\lib\axis-ant.jar omitted as C:\dev\src\tomcat6\work\verify\axis-ant.jar is up to date.
...
[copy] No sources found.
[echo] app2.lib.jars
...
For a one-time solution I extracted all the filenames from the
resource sets in the Ant file and compared that to a directory listing
of the result of copying all the files (in Ant) into a temporary
directory, after appropriate sorting.
Question: Is there a way to get Ant to tell me when a resource points
to a missing file, preferably at the time the resource is defined?

Here's an illustration of one method. Key points
Convert your files to filelists - these can contain names of files that don't exist in the file system, unlike filesets and files, that ignore entries that don't exist
Use a restrict to check for existence
Use a fail to error when something is missing
You'll need to add the "antlib:org.apache.tools.ant.types.resources.selectors" namespace to the project to use the resource selectors shown below. You'll hit snags with Ant versions older than 1.7.0.
<project name="so" default="checkfiles" basedir="."
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
<filelist id="app1.lib.jars">
<file name="${java}/jre/lib/jsse.jar"/>
<file name="${work.lib}/jtidy.jar"/>
...
</filelist>
<restrict id="missing.app1.lib.jars">
<filelist refid="app1.lib.jars"/>
<rsel:not>
<rsel:exists/>
</rsel:not>
</restrict>
<property name="missing.files" refid="missing.app1.lib.jars" />
<fail message="These files are missing: ${missing.files}">
<condition>
<length string="${missing.files}" when="greater" length="0" />
</condition>
</fail>
<pathconvert property="found.files" refid="app1.lib.jars" />
<echo message="Found files ${found.files}" />
Alternatively, you could use the 'copy' task, as you suggest, but with filelists instead of files.
The copy should fail when it tries to process the first resource that doesn't exist.

Related

Ant failing with Content is not allowed in prolog

I am using subant and it is resulting into Content is not allowed in prolog problem.
<subant target="main" genericantfile="build.xml">
<fileset dir = "." />
</subant>
Error:
The following error occurred while executing this line:
pattern.py:1: Content is not allowed in prolog.
Please note I have different files in those folders for example, python files.
When I use explicit listing using the filelist, all works fine.
<subant target="main" genericantfile="build.xml">
<filelist dir="."
files = "A/build.xml,
B/build.xml"
/>
</subant>
With subant you either specify genericantfile along with a dirset (to run the same build file many times, each time with a different basedir) or you omit genericantfile but supply a fileset or other resource collection of build files to run. You are mixing the two styles, and it looks like when you provide a fileset ant is ignoring the genericantfile attribute and treating each element of that fileset as a build file, attempting to parse each of the files as XML, and failing for those that are not XML (i.e. the python files).
<subant target="main">
<fileset dir = "." includes="**/build.xml" />
</subant>
would include only the real build files in the fileset.

No ruleset or basic.xml in the sourceforge pmd-bin-5.0.0 download

I've been reading all over the PMD Website and it has all these references to <rule ref="rulesets/basic.xml/UnnecessaryConversionTemporary"/> but I cant find the file basic.xml in either the pmd-bin-5.0.0 or pmd-bin-5.0-alpha directory downloaded from sourceforge.
As you can see in the screen dump I've provided below, I've done a search for this basic.xml and came up empty handed.
(source: iforce.co.nz)
In the next screen shot of pmd-bin-5.0.0 there is no folder called ruleset
(source: iforce.co.nz)
Pastebin link to ruleset.xml (Expires in 24 hours)
<property name="pmd.dir" value="${basedir}/pmd" /><!-- directory that contains pmd.jar -->
<property name="pmd.test.results" location="${build.dir}/pmd"/>
<path id="pmd.lib" >
<fileset dir="${pmd.dir}">
<include name="*.jar"/>
</fileset>
</path>
<target name="pmd" depends="compile" >
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask" classpathref="pmd.lib"/>
<pmd shortFilenames="true">
<ruleset>basic,imports</ruleset>
<formatter type="text" toFile="pmd-ant-results.txt"/>
<fileset dir="src">
<include name="**/*.java"/>
</fileset>
</pmd>
</target>
When my ant script is executed it comes back with this error
[pmd] net.sourceforge.pmd.RuleSetNotFoundException: Can't find resource rulesets/basic.xml. Make sure the resource is a valid file or URL or is on the CLASSPATH.
BUILD FAILED
C:\Users\Michael\Desktop\log4jassignment.s06005586\build.xml:131: java.lang.RuntimeException: Couldn't find the class Can't find resource rulesets/basic.xml. Make sure the resource is a valid file or URL or is on the CLASSPATH.
Project Explorer
(source: iforce.co.nz)
So that tells me that the basic.xml file doesn't come from the pmd-5.0.0.jar file but in fact comes from somewhere else, Thus my question is what is the contents of pmd's basic.xml, and other required xml files (how am I meant to get my hands on them)? or do these files not exist and am I meant to recreate them myself (and if I am, how would I go about doing this?)?
I downloaded pmd-bin-5.0-alpha.zip from PMD Website.
Once you unzip pmd-bin-5.0-alpha.zip file;
go inside the lib directory and
try to extract the content of pmd-5.0-alpha.jar.
I was able to find the following:

How to check if files in one directory exist in another directory?

I am looking for a means to have Ant check a target directory for the existence of files in a list/set defined by a source directory.
The Ant target only needs to determine if the files in a source directory also currently exist in the target directory. No copying/moving/deleting necessary.
Can this be done in Ant?
Take a look at the Ant resource collection set operators. For example:
<fileset id="source" dir="source_dir" />
<fileset id="target" dir="target_dir" />
<difference id="difference">
<resources refid="source"/>
<resources refid="target"/>
</difference>
<echo message="${toString:difference}" />
You can use a dirset if you're only interested in directories.

Ant Copying Empty Directories

I am still very new to ant and, although I know coldfusion, I don't know very much about java conventions, but I know that ant is built using java conventions. That being said I am working on an ant process to copy a project to a temp folder, change some code in the project, and then push the temp directory up to an FTP. I am trying to exclude all of my git, eclipse, and ant files from the copy so that my testing platform doesn't get cluttered. I setup a target to do the copy, but it seems that Ant not only is ignoring my excludes (which I am sure I wrote wrong), but it is only copying top level directories and files. No recursive copy. My current target is:
<target name="moveToTemp" depends="init">
<delete dir="./.ant/temp" />
<mkdir dir="./.ant/temp" />
<copy todir="./.ant/temp">
<fileset dir=".">
<include name="*" />
<exclude name=".*/**" />
<exclude name=".*" />
<exclude name="build.xml" />
<exclude name="settings.xml" />
<exclude name="WEB-INF/**" />
</fileset>
<filterset>
<filter token="set(environment='design')" value="set(environment='testing')" />
</filterset>
</copy>
</target>
I know that I am not doing my excludes right, but I don't know what I am doing wrong with them. I see double asterisks (**) used all the time in Ant but I can't figure out
By default an Ant fileset will (recursively) include all files under the specified directory, equivalent to:
<include name="**/*" />
That's the implicit include. If you supply an include, it overrides the implicit one.
Your include
<include name="*" />
Says 'match any file in the fileset directory', but that excludes traversal of subdirectories, hence your issue. Only files and the top-level directories are being copied.
See Patterns in the Ant docs for directory-based tasks: ** matches any directory tree (zero or more directories).
For your case you should be able to simply remove the 'include', so that the implicit 'include all' applies.
Suggest you also investigate the defaultexcludes task, which lets you set up this sort of thing once for the whole project.
Responding to the title of the question. You can include copy of empty directories as follows. (includeemptydirs attribute)
Example:
<copy includeemptydirs="true" todir="${directory}${file.separator}sentinel_files">
<fileset dir="${basedir}${file.separator}sentinel_files"/>
</copy>
Use the documentation provided in:
https://ant.apache.org/manual/Tasks/copy.html

How do I convert an Ant Path into a FileSet?

I'm writing an Ant script to package a project into a WAR file. The software consists of several projects with their own source directories, libraries, etc.
The WAR task has a nested element lib which I'm currently working on. I currently have a reference of the required libs as a Path (containing several FileSets, which I use in a classpath reference. The lib, however, wants the input to be a FileSet, and it refuses a Path.
I tried converting my Path into a FileSet, but then I didn't get it to work as a classpath elsewhere.
Is there a way to convert a Path into a FileSet? I would hate to copy-paste the directories.
<path id="compile.libs">
<fileset dir="${common.path}/lib" includes="*.jar"/>
<fileset dir="${data.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/lib" includes="*.jar"/>
<fileset dir="${gui.path}/WebContent/WEB-INF/lib" includes="*.jar"/>
</path>
...when used with <war ..><../> <lib refid="compile.libs"/> </war> leads to:
BUILD FAILED
build.xml:173: compile.libs doesn't denote a zipfileset or a fileset
Assuming the paths are absolute, you can first convert the Path to a comma-delimited list using <pathconvert>, and then convert the list back into a Fileset:
<!-- create path -->
<path id="foo.path">
<pathelement location="/foo/bar/baz.txt"/>
<pathelement location="/qux/quux/quuux.txt"/>
</path>
<!-- convert foo.path to foo.list -->
<pathconvert
refid="foo.path"
property="foo.list"
pathsep=","
dirsep="/"
>
<!--
<fileset> will want relative paths, so we need to strip
the leading /. result: "foo/bar/baz.txt,qux/quux/quuux.txt"
-->
<map from="/" to=""/>
</pathconvert>
<!-- convert foo.list to fileset -->
<fileset id="foo.fileset" dir="/" includes="${foo.list}"/>
(Note the above assumes Unix; you may need to fiddle a bit with separators and whatnot if you're on Windows or you want to make it platform-independent.)
You may have several choices.
You may provide more than one
<lib> nested element to <war>
task. Maybe this would be enough.
You may preassemble all of your
lib files in one temporary
directory and then just reference that
directory as a fileset.
There is an ant-contrib
PathToFileSet task, but it
requires a central root directory,
and this may not be a case with your
compile.libs layout.
Since Ant 1.8.0 you can use a mappedresources. Source: Ant script: Prevent duplication of JAR in javac-classpath war-lib
I think I would try option 1.
I solved this by staging the libs like this :
<copy todir="stage/libs" flatten="true">
<path refid="classpath" />
</copy>
and then using a in the WAR task.simple.
The jars in the classpath used to compile are not the same that needs to be packaged inside the war. For example: I'm sure you need servlet-api.jar to compile your project but you don't need it inside the war because the container provides it. And some jars aren't needed at compile time but at runtime.
I know I'm not answering your question, just want you to think what you are doing.

Resources