Is there a way to detect the properties of a file using ant.
For example: date created, date modified, size, etc...?
I can't find anything built in that allows me to do that.
Thanks
Correct, nothing built in.
The following example uses the groovy ant task to call the Java NIO libraries:
<project name="demo" default="build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<macrodef name="getMetadata">
<attribute name="file"/>
<sequential>
<groovy>
import java.nio.file.*
import java.nio.file.attribute.*
import java.text.*
def path = Paths.get("#{file}")
def attributes = Files.getFileAttributeView(path, BasicFileAttributeView.class).readAttributes()
def df = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.US)
properties.'#{file}_size' = attributes.size()
properties.'#{file}_ctime' = df.format(new Date(attributes.creationTime().toMillis()))
properties.'#{file}_mtime' = df.format(new Date(attributes.lastModifiedTime().toMillis()))
properties.'#{file}_atime' = df.format(new Date(attributes.lastAccessTime().toMillis()))
</groovy>
</sequential>
</macrodef>
<target name="build">
<getMetadata file="src/foo/bar/A.txt"/>
<echo message="File : src/foo/bar/A.txt"/>
<echo message="Size : ${src/foo/bar/A.txt_size}"/>
<echo message="Create time : ${src/foo/bar/A.txt_ctime}"/>
<echo message="Modified time : ${src/foo/bar/A.txt_mtime}"/>
<echo message="Last access time: ${src/foo/bar/A.txt_atime}"/>
</target>
</project>
Update
Run the following commands to install the groovy task jar into a location that ANT can use:
mkdir -p ~/.ant/lib
curl http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.3.7/groovy-all-2.3.7.jar -L -o ~/.ant/lib/groovy-all.jar
Additionally, I'm using ANT 1.9.4 and Java 1.7.0_25
Related
I have following ant configuration:
<project name="pcebuild" basedir="." default="updateDatabase" xmlns:liquibase="antlib:liquibase.integration.ant" >
<taskdef resource="liquibase/integration/ant/antlib.xml" uri="antlib:liquibase.integration.ant">
<classpath path="c:\Users\artur.skrzydlo\Documents\liquibase-3.3.2-bin\liquibase.jar"/>
</taskdef>
<property name="liquiChangeLogFile" value="${basedir}/liquibase/db.changelog-master.xml"/>
<property name="db.driver" value="oracle.jdbc.OracleDriver"/>
<property name="db.url" value="jdbc:oracle:thin:#websph:1521:XE"/>
<target name="updateDatabase" description="Updates database with new changes using Liquibase">
<liquibase:updateDatabase changeLogFile="${liquiChangeLogFile}" >
<liquibase:database driver="${db.driver}" url="${db.url}" user="${db.user}" password="${db.pasword}"/>
</liquibase:updateDatabase>
</target>
</project>
After running this task I get an error :
Class not found: oracle.jdbc.OracleDriver
According to documentation :
driver The fully qualified class name of the JDBC driver.
I suppose that this error may rise because there is no place where I place classpath to my ojdbc.jar file. I am able to run this update command from command line, however there I can specify "classpath" argument which point to my ojdbc.jar file. And I don's see any place in this ant task definition where could i place it such a path. How can I do this ? What am I doing wrong ?
In your <liquibase:updateDatabase> tag you can have a classpathref attribute. So I have something like this:
<path id="driver.classpath">
<filelist files="${classpath}" />
</path>
...
<liquibase:updateDatabase
databaseref="main-schema"
changelogfile="${changeLogFile}"
classpathref="driver.classpath"
logLevel="debug"
>
...
And ${classpath} is an Ant property, set in a properties file:
classpath: /Users/me/place/lib/classes12.jar
I have something like:
<groovy>
import org.apache.tools.ant.types.FileSet
import org.apache.tools.ant.types.selectors.FilenameSelector
def aoeu = new FileSet()
aoeu.setDir(new File('aoeu'))
def snth = new new FilenameSelector()
snth.setName('snth')
aoeu.add(snth)
project.references['aoeu'] = aoeu
</groovy>
But:
<echo message="${toString:aoeu}"/>
emits a NullPointerException.
How can the above be fixed?
The groovy task has preconfigured bindings to an instance of AntBuilder and the Ant "project" object. It makes groovy very attractive for creating programmed logic within the build.
The following example demonstrates how the fileset can be created within the groovy script:
<project name="demo" default="process-text-files">
<path id="build.path">
<pathelement location="/path/to/jars/groovy-all-2.1.1.jar"/>
</path>
<target name="process-text-files">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
ant.fileset(id:"textfiles",dir:"src", includes:"**/*.txt")
project.references.textfiles.each {
println it
}
</groovy>
</target>
</project>
The following example demonstrates referencing a normal fileset created externally to the script (my preferred way to do it):
Ant : Process the files in the subfolder using tasks
I have an ant script that imports other scripts which import additional scripts leading to web of places where definitions can happen.
Can ant pull in all the definitions and output a file much like maven's help:effective-pom?
I'd like to add this as an output file with my build to make debugging somewhat easier.
You can create another target which will create that kind of file. For example it can look like this:
main build.xml which do some work and also can generate effective build:
<project name="testxml" default="build">
<import file="build1.xml" />
<import file="build2.xml" />
<target name="build">
<echo>build project</echo>
</target>
<target name="effective.build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpath="C:\Program Files (x86)\groovy-2.1.4\embeddable\groovy-all-2.1.4.jar" />
<groovy>
def regex = ~/import file="(.*)"/
def buildXmlContent = new File('build.xml').text
new File('build.xml').eachLine {
line -> regex.matcher(line).find() {
def file = new File(it[1])
if (file.exists()) {
def replacement = file.getText().replaceAll(/<project.*/, '').replaceAll(/<\/project.*/, '')
buildXmlContent = buildXmlContent.replaceFirst(/<import.*/, replacement)
}
}
}
new File('build.effective.xml') << buildXmlContent
</groovy>
</target>
</project>
Two build.xml's created for tests:
<project name="testxml2" default="build">
<target name="clean">
<echo>clean project</echo>
</target>
</project>
<project name="testxml1" default="build">
<target name="test">
<echo>test project</echo>
</target>
</project>
If you will run ant effective.build you will get new build.effective.xml file with this content:
<project name="testxml" default="build">
<target name="test">
<echo>test project</echo>
</target>
<target name="clean">
<echo>clean project</echo>
</target>
<target name="build">
<echo>build project</echo>
</target>
<target name="effective.build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpath="C:\Program Files (x86)\groovy-2.1.4\embeddable\groovy-all-2.1.4.jar" />
<groovy>
import java.util.regex.Pattern
def regex = ~/import file="(.*)"/
def buildXmlContent = new File('build.xml').text
new File('build.xml').eachLine {
line -> regex.matcher(line).find() {
def file = new File(it[1])
if (file.exists()) {
def replacement = file.getText().replaceAll(/<project.*/, '').replaceAll(/<\/project.*/, '')
buildXmlContent = buildXmlContent.replaceFirst(/<import.*/, replacement)
}
}
}
new File('build.effective.xml') << buildXmlContent
</groovy>
</target>
</project>
I chose groovy (because I learn it actually) for this purpose but you can create it in another langage. You can also compile this groovy code to ant task and use it as new task, for example <effectiveant outfile="build.effective.xml">. My example isn't perfect but it shows one of the solutions.
I have an Ant script file in which I use concat task to create a Java cource file in the specified package which is defined in a properties file.
For example, I define the package name:
ma.package=com.my.package
In Ant script, I call:
<concat destfile="./${prject.root}/${ma.package}/MyClass.java">
However, MyClass.java was created in a subfolder com.my.package, instead of folder structure com\my\package. How to fix it?
I use Eclipse Helios under Windows XP.
You can use a PathConvert with a nested UnpackageMapper to convert the package name to a path. For example:
<project default="test">
<property name="ma.package" value="com.my.package"/>
<target name="test">
<pathconvert property="ma.package.dir">
<path path="${ma.package}"/>
<unpackagemapper from="*" to="*"/>
</pathconvert>
<echo message="ma.package : ${ma.package}"/>
<echo message="ma.package.dir : ${ma.package.dir}"/>
</target>
</project>
The output is:
Buildfile: C:\tmp\ant\build.xml
test:
[echo] ma.package : com.my.package
[echo] ma.package.dir : C:\tmp\ant\com\my\package
So you could use the converted property value in your concat:
<concat destfile="${ma.package.dir}/MyClass.java">
I'm using a groovy code snippet in an ant build file. Inside the groovy code I'm trying to reference a fileset that has been defined outside of the groovy part, like this:
<target name="listSourceFiles" >
<fileset id="myfileset" dir="${my.dir}">
<patternset refid="mypatterns"/>
</fileset>
<groovy>
def ant = new AntBuilder()
scanner = ant.fileScanner {
fileset(refid:"myfileset")
}
...
</groovy>
</target>
When I execute this I get the following error message:
Buildfile: build.xml
listSourceFiles:
[groovy]
BUILD FAILED
d:\workspace\Project\ant\build.xml:13:
Reference myfileset not found.
What am I missing?
According to the Groovy Ant Task documentation, one of the bindings for the groovy task is the current AntBuilder, ant.
So modifying your script to drop the clashing 'ant' def I got it to run with no errors:
<project name="groovy-build" default="listSourceFiles">
<taskdef name="groovy"
classname="org.codehaus.groovy.ant.Groovy"/>
<patternset id="mypatterns">
<include name="../*.groovy"/>
</patternset>
<target name="listSourceFiles" >
<fileset id="myfileset" dir="${my.dir}">
<patternset refid="mypatterns"/>
</fileset>
<groovy>
scanner = ant.fileScanner {
fileset(refid:"myfileset")
}
</groovy>
</target>
</project>