Is ANT copy task case-sensitive? - ant

I am trying to copy a file inside my ANT build script. For example the below copy statement -
<copy file="myfile.txt" tofile="mycopy.txt"/>
My doubt is- if by mistake/chance the physical file name becomes myFile.txt or MyFile.txt or MYFILE.txt, will the above statement still work??
I am unable to find any relevant documentation for the same. Please clarify if you are aware. Thanks.
UPDATE- I am aware that if I use fileset, I will be able to use 'casesensitive' attribute of fileset. But, I'm just using the 'file' type.

At the bottom of the copy page, it mentions if a file with a different case exists in windows, it copies over it. This to me indicates it's OS dependent, hence linux would be case sensitive and Windows not so much.
https://ant.apache.org/manual/Tasks/copy.html

As you've already said, fileset allows you to control case-sensitivity.
When using the file attribute the task's copySingleFile method kicks in which uses File#exists to determine whether there is anything to copy. exists is case-sensitive on Unix-like systems and insensitive on Windows. So using the file attribute is platform dependent.
Given your doubt you probably want to use something like
<copy tofile="mycopy.txt">
<fileset file="myfile.txt" casesensitive="false"/>
</copy>

Related

ANT invert (reverse) directory structure

How can I reverse the directory structure for files using Ant.
For example, I have the following
C:\some\path\a\b\file1.txt
C:\some\path\y\z\file2.txt
I would like to convert this to
C:\some\dir\b\a\file1.txt
C:\some\dir\z\y\file2.txt
In terms of variables in Ant, I know C:\some\path and C:\some\dir, but I don't know the directories a,b,y,z (those are entirely dynamic).
Ideally it would to be a separate directory (e.g. from path -> dir), but in-place is OK to since I can just copy elsewhere first.
I thought globmatcher/regexmatcher might help, but I think they only change the file name, not the directory name.
There is actually a somewhat relevant sample in the ant docs for mapper
Just use the regex mapper during the move or copy and reverse the directory order in the match:
<mapper type="regexp" from="^(.*)/([^/]+)/([^/]*)$$" to="\2/\1/-\3"/>

Ant file path question

I have an Ant file that has this as a path. TRying to find out what it might mean.
deploy.dir = ${basedir}/..
First there is nowhere I can find where ${basedir} is being set. Is this some variable type being set in another file on the server or does ${basedir} mean the same directory the build file is in?
Then what does /.. mean after it.
Thanks
http://ant.apache.org/manual/using.html will explain that ${basedir} is, by default, where you are sitting when you type 'ant'.
.. means what it means on Windows and Linux in pathnames: one directory up.
The default value of ${basedir} is the directory containing your build xml file. This is even true if you say basedir="." in the project element. However, if on the command line, you say:
-Dbasedir=.
then it will be where you are sitting when executing ant. Since in most cases the build xml file will be where you are sitting, the difference shouldn't matter.

How can I post-process files compiled using the Ant javac task?

I need the list of files that were compiled during this run. I want to feed this list to a subsequent post-processing step.
I have found an option to list (see listfiles option) the files compiled during this run, but it seems only good for displaying the list on console.
Any idea?
Edit: I am talking about incremental compiles, so taking a fileset of the build folder is not an option.
Edit: One idea seems to be custom logger but I am still looking for something simpler
Edit: Another idea is to use depend selector with FileSet before javac and somehow keep the list in memory, to be used after javac has executed
You simply can form a fileset about all class-files in the target-directory of the javac.
Edit: After the clarification I have to adjust my answer. I didn't such thing yet, but I would try my luck with selectors. The modified-selector looks like the one you want - a fileset of all class-files in a directory, that have changed since the last run. Here is a code-snippet:
<fileset dir="${build}">
<filename name="**/*.class"/>
<modified/>
</fileset>
It does not directly post-process the output of the javac-task, but should solve your problem.

xmltask confused about dtd

I'm trying to use xmltask for ant to modify a file in a subdirectory:
project/path/to/file.xml
The file refers to a DTD like this:
<!DOCTYPE data SYSTEM "mydtd.dtd">
I don't have the flexibility to change these documents.
This DTD is stored in the same subdirectory, which has always worked fine:
project/path/to/mydtd.dtd
Unfortunately, xmltask is trying to locate the dtd in my project's top-level directory, which is where my build file is located, and where I run from:
[xmltask] java.io.FileNotFoundException: /home/me/project/mydtd.dtd (The system cannot find the file specified)
I see in the xmltask documentation that I can correct this with an xmlcatalog element to tell it where to look up the file. But I need to use a dtd element, and I can only find examples for this element, not documentation; the examples show only a publicId, and if I understand XML correctly this document does not have one. I shouldn't need to specify this, anyway, right, since my document already says my DTD is stored locally and shows right where it is?
Why isn't xmltask finding the DTD correctly? What's the best way to correct or work around this situation?
An XML Catalog is the way to go here, it just needs a bit more perseverance.
As you correctly pointed out, the standard Ant <XmlCatalog> type only allows you to specify public DTD references when using the inline syntax, which is of no use to you. However, <XmlCatalog> also lets you specify a standard OASIS-syntax catalog, which is far richer, including resolving SYSTEM DTD references.
An OASIS catalog (full spec here) looks like this:
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="mydtd.dtd" uri="project/path/to/mydtd.dtd"/>
</catalog>
You can then reference this catalog from the <XmlCatalog>:
<xmlcatalog refid="commonDTDs"/>
<catalogpath>
<pathelement location="path/to/oasis.catalog"/>
</catalogpath>
</xmlcatalog>
And that's that. It's a good idea to build up a reusable OASIS catalog file, and refer to it from various XML-related Ant tasks, all of which can use <XmlCatalog>.
As an alternative, it looks like I can skip the whole validation by creating a blank file with the same name as the DVD file, and then deleting the file when I am done. Odds are I am going to go that route instead of using the catalog.
xmltask isn't finding it because it is looking in the current working directory. Ant allows you to specify a base directory using the basedir attribute of the <target> element. So I suggest you try this:
<target basedir="path/to" ...>
<xmltask...
</target>
It strikes me that it is not the XML/DTD that you really have the problem with, but getting xmltask to interact with the two of them as you want.
If that fails, you could use the Ant Copy task to copy the XML and DTD to the root folder before processing with xmltask, then copying back again.
Have you tried:
<!DOCTYPE data SYSTEM "./path/to/mydtd.dtd">
? Or an absolute path?
Also, you can find <dtd> description here.
I had a similar problem where an XML file had a doctype with SYSTEM reference that could not be changed.
<!DOCTYPE opencms SYSTEM "http://www.opencms.org/dtd/6.0/opencms-modules.dtd">
I first went down the road and created a catalog file with the OASIS catalog as described above, but to be able to use external catalogs I had to include the Apache Commons Resolver 1.1 (resolver.jar) in the Ant classpath (see http://ant.apache.org/manual/Types/xmlcatalog.html).
Because I had multiple machines on which this build was supposed to run this seemed overkill, especially since xmltask worked fine if I just removed the doctype definition. I wasn't allowed to remove it permanently because the doctype was needed elsewhere.
Ultimately I used this workaround: I commented out the doctype definition using Ant's replace task, ran the xmltask, and then put the doctype back into the file.
<replace file="myxmlfile.xml">
<replacetoken><!DOCTYPE opencms SYSTEM "http://www.opencms.org/dtd/6.0/opencms-modules.dtd"></replacetoken>
<replacevalue><!-- !DOCTYPE opencms SYSTEM "http://www.opencms.org/dtd/6.0/opencms-modules.dtd" --></replacevalue>
</replace>
<xmltask .../>
<replace file="${local.opencms.webapp.webinf}/config/opencms-modules.xml">
<replacetoken><!-- !DOCTYPE opencms SYSTEM "http://www.opencms.org/dtd/6.0/opencms-modules.dtd" --></replacetoken>
<replacevalue><!DOCTYPE opencms SYSTEM "http://www.opencms.org/dtd/6.0/opencms-modules.dtd"></replacevalue>
</replace>

Reasons for using Ant Properties files over "Properties Tasks"

I'm currently working with some developers who like to set up Ant tasks that define environment specific variables rather than using properties files. It seems they prefer to do this because it's easier to type:
ant <environment task> dist
Than it is to type:
ant -propertyfile <environment property file> dist
So for example:
<project name="whatever" default="dist">
<target name="local">
<property name="webXml" value="WebContent/WEB-INF/web-local.xml"/>
</target>
<target name="remote">
<property name="webXml" value="WebContent/WEB-INF/web-remote.xml"/>
</target>
<target name="build">
<!-- build tasks here --->
</target>
<target name="dist" depends="build">
<war destfile="/dist/foo.war" webxml="${webXml}">
<!-- rest of war tasks here -->
</war>
</target>
I am finding it hard to convince them that properties files are they right way to go. I believe properties files are better because:
They provides more flexibility - if you need a new environment just add a new properties file
It's clearer what's going on - You have to know about this little "trick" to realize what they're accomplishing
Doesn't provide default values and the ability to use overrides - if they used property files they could provide defaults at the top of the project but have the ability to override them with a file
Script won't break if an environment task isn't supplied on command line
Of course all they hear is that they need to change their Ant script and have to type more on the command line.
Can you provide any additional arguments in favor of properties files over "property tasks"?
Properties tasks tightly couple the build file to environments. If your fellow developers are arguing that they "have to change their ant script" with your suggestions, why aren't they arguing about changing it every time they have to deploy to a new environment? :)
Perhaps you can convince them to allow both properties file and command-line configuration. I set up my Ant builds so that if a build.properties exists in the same directory as the build.xml, it reads it in. Otherwise it uses a set of default properties hard-coded into the build. This is very flexible.
<project name="example">
<property file="build.properties"/>
<property name="foo.property" value="foo"/>
<property name="bar.property" value="bar"/>
...
</project>
I don't provide a build.properties with the project (i.e. build.properties is not versioned in SCM). This way developers aren't forced to use the property file. I do provide a build.properties.example file that developers can reference.
Since Ant properties, once set, are immutable, the build file will use properties defined in this order:
Properties provided with -D or -propertyfile via the command line
Properties loaded from build.properties
Default properties within build.xml
Advantages of this approach:
The build file is smaller and therefore more maintainable, less bug-prone
Developers that just can't get away from setting properties at the command line can still use them.
Properties files can be used, but aren't required
The arguments you have are already pretty compelling. If those arguments haven't worked, then arguing isn't going to solve the problem. In fact, nothing is going to solve the problem. Don't assume that people are rational and will do the most practical thing. Their egos are involved.
Stop arguing. Even if you win, the resentment and irritation you create will not be worth it. Winning an argument can be worse than losing.
Make your case, then let it go. It's possible that after a while they will decide to switch to your way (because it actually is better). If that happens, they will act like it was their own idea. There will be no mention of your having proposed it.
On the other hand, they may never switch.
The only solution is to work towards a position of authority, where you can say how things are to be done.
The problem with the first solution (using ant property) is basically hardcoding.
It can be convenient when you start a project for yourself but quickly you have to remove that bad habit.
I'm using a property file close to what said robhruska except that I have committed the build.properties file directly. This way you have a default one.
In other hand, I understand I could add those default values in the build.xml. (I will probably try that in the next hours/days ;-) ).
Anyway, I really don't like the first approach and I would force those guys to follow the second one ...

Resources