Ant Copy task with Path instead of FileSet - ant

I'm using Ant 1.7, want to copy files from different paths (they have no relationship, so i cannot use the include selector to filter them out of their root directory). I try to use the <path> inside the <copy> instead of <fileset>, because with <path> i can specify multi paths which is in <fileset> not possible. My ant script looks like this, but it doesn't work.
<target name="copytest">
<!-- copy all files in test1 and test2 into test3 -->
<copy todir="E:/test3">
<path>
<pathelement path="C:/test1;D:/test2"></pathelement>
</path>
</copy>
</target>
Anybody has idea about how to use the <path> inside <copy>? Or maybe anybody has the advise about how to copy files from different source without selector?
Btw, i don't want to hard code the source directories, they will be read from a propertiy file, so writing multi <fileset> inside <copy> should not be considered.
thanks in advance!

This only works if the flatten attribute is set to true:
<copy todir="E:/test3" flatten="true">
<path>
<pathelement path="C:/test1;D:/test2"></pathelement>
</path>
</copy>
This is documented in the Examples section of the Ant Copy task documentation.

<pathelement> generally uses it's path attribute as a reference to classpath or some other predefined location, if you want to give specific file locations outside of the classpath try with location attribute
<pathelement location="D:\lib\helper.jar"/>
The location attribute specifies a single file or directory relative
to the project's base directory (or an absolute filename), while the
path attribute accepts colon- or semicolon-separated lists of
locations. The path attribute is intended to be used with predefined
paths - in any other case, multiple elements with location attributes
should be preferred.

We have the same problem
A bit more complicated that we need to add a specified pattern set to each fileset converted from path
For example, this is the incoming data
<path id="myDirList" path="C:/test1;D:/test2" />
<patternset id="myPatterns" includes="*.html, *.css, etc, " />
We wrote a script to solve this problem
<resources id="myFilesetGroup">
<!-- mulitiple filesets to be generated here
<fileset dir="... dir1, dir2 ...">
<patternset refid="myPatterns"/>
</fileset>
-->
</resources>
<script language="javascript"><![CDATA[
(function () {
var resources = project.getReference("myFilesetGroup");
var sourceDirs = project.getReference("myDirList").list();
var patterRef = new Packages.org.apache.tools.ant.types.Reference(project, "myPatterns");
for (var i = 0; i < sourceDirs.length; i++) {
var fileSet = project.createDataType("fileset");
fileSet.dir = new java.io.File(sourceDirs[i]);
fileSet.createPatternSet().refid = patterRef;
resources.add(fileSet);
}
})();
]]></script>
now you can use this resources in you copy task
<!-- copy all files in test1 and test2 into test3 -->
<copy todir="E:/test3">
<resources refid="myFilesetGroup">
</copy>

I tried this and works fine
<fileset file="${jackson.jaxrs.lib}"/>

Related

yguard not updating properties file in the jar

I have jar file having some properties files in it like log4j.properties and config.properties. Following is my ant script for yguard. Everything else is working but the properties file updation.
<target name="yguard">
<taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="lib/yguard.jar" />
<yguard>
<inoutpairs resources="none">
<fileset dir="${basedir}">
<include name="MyApp.jar" />
</fileset>
<mapper type="glob" from="MyApp.jar" to="MyAppObs.jar" />
</inoutpairs>
<externalclasses>
<pathelement location="lib/log4j-1.2.17.jar" />
</externalclasses>
<rename conservemanifest="true" mainclass="com.amit.Application" >
<adjust replaceContent="true" >
<include name="**/*.properties" />
</adjust>
</rename>
</yguard>
</target>
config.properties file
com.amit.Application.param1 = something
I found some question in stackoverflow but they didn't help. One place it was mentioned that the file (like jsp, xml, properties) should be in the jar file which I already have. But my yguard obfuscated file just get the files copied as it is.
I tried many combinations with rename & adjust tags but nothing worked for me.
Following post I already visited
Is it possible to manage logs through Obfuscation with yGuard?
How to include obfuscated jar file into a war file
Apparently you want yGuard to obfuscate the name of the field param1, because com.amit.Application is obviously your entry point and yGuard excludes the given main class automatically. So basically you want the outcome to be something like
com.amit.Application.AÖÜF = something
This isn't possible, because yGuard can only adjust class names in property files, as state here: yGuard Manual

How to identify if a file is copied from a particular archive?

I am new to ANT.
I have a very specific scenario to handle in this:
STEP-1: I need to look for the pattern of filenames in certain ear files. If the pattern matches then I need to extract those files.
STEP-2: And if any file is extracted from a certain ear (similar to zip-file) file, then I need to search for another set of files, and copy those set of files too.
The case to handle is "How to identify if a file is copied from a particular archive" if found then proceed to step 2, else move to next archive.
I have achieved STEP-1 but no idea how to achieve step-2.
STEP-1
<!-- Set via arguments passed -->
<patternset id="pattern.needtocopy" includes="${needtocopyfile.pattern}" excludes="${ignore.pattern}">
</patternset>
<target name="get-binaries-from-baseline">
<for param="binary">
<path>
<fileset dir="${baseline.dir}/target/aaa/bbb/ccc" includes="*.ear" />
</path>
<sequential>
<basename file="#{binary}" property="#{binary}.basename" />
<unzip src="#{binary}" dest="${baseline.dir}">
<patternset refid="pattern.needtocopy" />
<mapper type="flatten" />
</unzip>
</sequential>
</for>
</target>
STEP-2:
????
Need help in this.
Thanks.
Well I resolved the same, using a groovy script based on the resources I could find.
<target name="findJars">
<zipfileset id="found" src="${ear-name}">
<patternset refid="${patternsetref}" />
</zipfileset>
<groovy>
project.references.found.each {
println it.name
println project.properties.'ear-name'
println project.properties.'dest.dir'
}
</groovy>
</target>
And then I added another task which takes this filename and ear-file-name as input and extracts the related jars based on file to search pattern.

ANT: Foreach not excluding files when target attrbute is used

I have a foreach tag to execute all the files within a particular directory. As part of the fileset I have excluded two files.
But irrespective of excluding the files, the param still passes the two files to the target "runpART"
I do not want to call the target for the excluded files.
Let me know if there is any way to do it. The following does not seem to work
<foreach target="runART" param="p.schedulerFile" inheritall="true" inheritrefs="true">
<path>
<fileset dir="${p.dir}" casesensitive="no">
<!--<include name="**\*.xml"/>-->
<excludesfile name="${pART.dir}\CodeCoverage_NSR.xml"/>
<excludesfile name="${pART.dir}\CodeCoverageRegression_HLR.xml"/>
</fileset>
</path>
</foreach>
You don't want <excludesfile >, which expects a file containing exclude patterns, you want
<exclude name="CodeCoverage_NSR.xml">
<exclude name="CodeCoverageRegression_HLR.xml">
Now, that's assuming you meant to have ${p.dir} == ${pART.dir}.
Exclude patterns in a fileset have to be relative to the root dir of the fileset (here, its dir="${p.dir}").
For more info, see: http://ant.apache.org/manual/Types/fileset.html

Deleting files matching a placeholders in another directory tree

I have two directory trees:
source/aaa/bbb/ccc/file01.txt
source/aaa/bbb/file02.txt
source/aaa/bbb/file03.txt
source/aaa/ddd/file03.txt
source/file01.txt
and
template/aaa/bbb/ccc/file01.txt
template/aaa/bbb/DELETE-file03.txt
template/aaa/DELETE-ddd
template/DELETE-file01.txt
Using Ant, I want to do three things. First, I want to copy any files from "template" into "source", such that all files not starting with "DELETE-" are replaced. For example, "source/aaa/bbb/ccc/file01.txt" would be replaced. This is straightforward with:
<copy todir="source" verbose="true" overwrite="true">
<fileset dir="template">
<exclude name="**/DELETE-*"/>
</fileset>
</copy>
Second, I want to delete all files in the "source" tree whose name matches a "DELETE-" file in the corresponding directory of the "template" tree. For example, both "source/aaa/bbb/file03.txt" and "source/file01.txt" will be deleted. I have been able to accomplish this with:
<delete verbose="true">
<fileset dir="source">
<present present="both" targetdir="template">
<mapper type="regexp" from="(.*[/\\])?([^/\\]+)" to="\1DELETE-\2"/>
</present>
</fileset>
</delete>
Third, I'd like to delete any directories (empty or not) whose names match in the same way. For example, "template/aaa/DELETE-ddd" and all file(s) under it would be deleted. I'm not sure how to construct a fileset that matches directories (and all the files under them) in the "source" tree where the directory has a DELETE-* file in the "template" tree.
Is this third task even possible with Ant (1.7.1)? I'd preferrably like to do this without writing any custom ant tasks/selectors.
It seems the root issue that makes this difficult is that ant drives selectors/filesets based on files found within the target directory of fileset. Normally, however, one would want to drive things from the list of DELETE-* marker files.
The best solution I've found so far does require some custom code. I chose the <groovy> task, but also could have used <script>.
The gist: create a fileset, use groovy to add a series of excludes that skip files and directories with a DELETE-* marker, then perform the copy. This accomplishes the second and third task from my question.
<fileset id="source_files" dir="source"/>
<!-- add exclude patterns to fileset that will skip any files with a DELETE-* marker -->
<groovy><![CDATA[
def excludes = []
new File( "template" ).eachFileRecurse(){ File templateFile ->
if( templateFile.name =~ /DELETE-*/ ){
// file path relative to template dir
def relativeFile = templateFile.toString().substring( "template".length() )
// filename with DELETE- prefix removed
def withoutPrefix = relativeFile.replaceFirst( "DELETE-", "")
// add wildcard to match all files under directories
def exclude = withoutPrefix + "/**"
excludes << exclude
}
}
def fileSet = project.getReference("source_files")
fileSet.appendExcludes(excludes as String[])
]]></groovy>
<!-- create a baseline copy, excluding files with DELETE-* markers in the template directories -->
<copy todir="target">
<fileset refid="source_files"/>
</copy>
To delete a directory and its contents use delete with nested fileset, i.e. :
<delete includeemptydirs="true">
<fileset dir="your/root/directory" defaultexcludes="false">
<include name="**/DELETE-*/**" />
</fileset>
</delete>
With attribute includeemptydirs="true" the directories will be deleted too.

Ant: Rename files to include their MD5

The question is likely VERY trivial for anyone familiar with ant, of which I only use the basics thus far.
I know how to rename files, e.g. I already use:
<copy todir="build/css/">
<fileset dir="css/">
<include name="*.css"/>
</fileset>
<globmapper from="*.css" to="*-min.css"/>
</copy>
I know how to calculate an MD5:
<checksum file="foo.bar" property="foobarMD5"/>
I don't know how to include the second into the first, to rename all those files to include their MD5 - the purpose is to serve as webbrowser cache buster. The other cache-busting option, to append "?[something]" is not as good, as is explained on some Google webmaster pages, having the MD5 as part of the name is better.
I managed to produce a somewhat strange solution using for from ant contrib.
But you have to install ant contrib first.
The copy in the sequential does not seem to accept/evaluate mappers (it wouldn't work, I tried with ant 1.7.0), so I had to create an extra move with a filtermapper to create the results.
It does the following:
for each file create an md5sum and save it in property foobarMD5
the property has to be unset before each iteration
I create a new file in the same dir named example.java_foobarMD5.java (Notice that the filename contains the fileextension)
I move all files with .java_ in its name to a new Folder and remove the .java_
I leave this example with .java.
<for param="file">
<path>
<fileset dir="src/" includes="**/*.java"/>
</path>
<sequential>
<echo>Letter #{file}</echo>
<var name="foobarMD5" unset="true"/>
<checksum file="#{file}" property="foobarMD5"/>
<echo>${foobarMD5}</echo>
<copy file="#{file}" tofile="#{file}_${foobarMD5}.java"/>
</sequential>
</for>
<move todir="teststack" verbose="true">
<fileset dir="src/">
<include name="**/*java_*"/>
</fileset>
<filtermapper>
<replacestring from=".java_" to="-"/>
</filtermapper>
</move>
You could do this without having to include ant contrib. I had to implement this for work and was not allowed to introduce that extension for security reasons. The solution I came to was this:
<target name="appendMD5">
<copy todir="teststack">
<fileset dir="css/" includes="**/*.css"/>
<scriptmapper language="javascript"><![CDATA[
var File = Java.type('java.io.File');
var Files = Java.type('java.nio.file.Files');
var MessageDigest = Java.type('java.security.MessageDigest');
var DatatypeConverter = Java.type('javax.xml.bind.DatatypeConverter');
var buildDir = MyProject.getProperty('builddir');
var md5Digest = MessageDigest.getInstance('MD5');
var file = new File(buildDir, source);
var fileContents = FIles.readAllBytes(file.toPath());
var hash = DatatypeConverter.printHexBinary(md5Digest.digest(fileContents));
var baseName = source.substring(0, source.lastIndexOf('.'));
var extension = source.substring(source.lastIndexOf('.'));
self.addMappedName(baseName + '-' + hash + extension);
]]></scriptmapper>
</copy>
</target>
It is worth noting that I wrote this for Java 8 but with some minor tweaks it could work on Java 7. Sadly this won't work for earlier versions of Java without more effort.

Resources