Ant: Find the path of a file in a directory - file

I want to find the path of a file in a directory (similar to unix 'find' command or the 'which' command, but I need it to work platform-independent) and save it as a property.
Tried to use the whichresource ant task, but it doesn't do the trick (I think it's only good for looking inside jar files).
I would prefer if it would be pure ant and not to write my own task or use a 3rd-party extension.
Notice that there might be several instances of a file by that name in the path - I want it to only return the first instance (or at least I want to be able to choose only one).
Any suggestions?

One possibility is to use the first resource selector. For example to find a file called a.jar somewhere under directory jars:
<first id="first">
<fileset dir="jars" includes="**/a.jar" />
</first>
<echo message="${toString:first}" />
If there are no matching files nothing will be echoed, otherwise you'll get the path to the first match.

Here is an example which selects the first matching file. The logic is as follows:
find all matches using a fileset.
using pathconvert, store the result in a property, separating each matching file with line separator.
use a head filter to match the first matching file.
The functionality is encapsulated in a macrodef for reusability.
<project default="test">
<target name="test">
<find dir="test" name="*" property="match.1"/>
<echo message="found: ${match.1}"/>
<find dir="test" name="*.html" property="match.2"/>
<echo message="found: ${match.2}"/>
</target>
<macrodef name="find">
<attribute name="dir"/>
<attribute name="name"/>
<attribute name="property"/>
<sequential>
<pathconvert property="#{property}.matches" pathsep="${line.separator}">
<fileset dir="#{dir}">
<include name="#{name}"/>
</fileset>
</pathconvert>
<loadresource property="#{property}">
<string value="${#{property}.matches}"/>
<filterchain>
<headfilter lines="1"/>
</filterchain>
</loadresource>
</sequential>
</macrodef>
</project>

I created a macro based on martin-clayton's answer.
sample project with macro and a property file that is read from the found file
<?xml version="1.0" encoding="utf-8"?>
<project name="test properties file read" default="info">
<macrodef name="searchfile">
<attribute name="file" />
<attribute name="path" default="custom,." />
<attribute name="name" />
<sequential>
<first id="#{name}">
<multirootfileset basedirs="#{path}" includes="#{file}" erroronmissingdir="false" />
</first>
<property name="#{name}" value="${toString:#{name}}" />
</sequential>
</macrodef>
<searchfile name="custom.properties.file" file="config.properties" />
<property file="${custom.properties.file}" />
<target name="info" >
<echo>
origin ${config.origin}
</echo>
</target>

Related

log4net log file not being written when the app is deployed

I have a WPF app that uses log4net. When I run it in Visual Studio, the log file is created in the Debug or Release folder as expected.
However, when I create an installer and run the installed app, the log file is not created. I added the following lines to the code...
string logFilePath = ((Hierarchy)LogManager.GetRepository())
.Root.Appenders.OfType<FileAppender>()
.FirstOrDefault()?.File;
using (StreamWriter sw = new StreamWriter(#"d:\log.log")) {
sw.WriteLine("Log file: " + logFilePath);
}
...to enable me to check that the log file was being written in the location I expected. It showed me that the log file was supposed to be written to C:\Program Files (x86)\Physio Diary\PhysioDiaryClient.log which is what I expected.
However, the file doesn't exist. Any idea why?
Here is the top of the App.config file...
<?xml version="1.0"
encoding="utf-8"?>
<configuration>
<configSections>
<section name="log4net"
type="log4net.Config.Log4NetConfigurationSectionHandler,Log4net" />
</configSections>
<log4net>
<appender name="RollingFileAppender"
type="log4net.Appender.RollingFileAppender">
<param name="File"
value="PhysioDiaryClient.log" />
<appendToFile value="true" />
<rollingStyle value="Size" />
<maxSizeRollBackups value="2" />
<maximumFileSize value="1MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-7level %logger - %message%newline%exception" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="RollingFileAppender" />
</root>
</log4net>
The bottom of the file looks like this...
<startup>
<supportedRuntime version="v4.0"
sku=".NETFramework,Version=v4.5.2" />
</startup>
</configuration>
The bits in between are all to do with the WCF services that the app uses.
Anyone any ideas?
Edit: As a test, I tried hard-coding the log file path in App.config to my D: drive (so it's hard-coded, and no question of a permissions issue), but the file still wasn't created.
Thanks to #dymanoid for pointing me in the right direction. The log4net docs are a bit weak in this area, but I found this answer that pointed out that you can use normal environment variables in the config file.
With the aid of this list of environment variables, I ended up with the following...
<param name="File"
value="${LOCALAPPDATA}\Physio Diary\PhysioDiaryClient.log" />
This correctly write the file to C:\Users\MyUsername\AppData\Local\Physio Diary\PhysioDiaryClient.log
Hope this helps someone.

create a new file from payload in wso2

I am new to wso2 and working on a few POCs where i have to create a file at some location , i have looked into all vfs examples where there is always a file processed and written to a new location.
What i want to achieve is write a new file to a directory by the content i receive in a sequence.
For my requirement process i have exposed a REST service and it calls this sequence.
The sequence configuration is as follows.
<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="FileWriteSequence">
<clone>
<target>
<sequence>
<property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
<property name="transport.vfs.ReplyFileName" value="myOutputFile.txt" scope="transport" type="STRING"/>
<send>
<endpoint name="FileEpr">
<address uri="vfs:file://D:/Tools"/>
</endpoint>
</send>
</sequence>
</target>
</clone>
This sequence creates a file from the latest message from the REST resource but the file name is always the project name.
Whatever i try it doesnt change.
I have tried giving other proxy parameters shown below as property above my sequence as well .Instead of paramters i passed them above the property <property name="OUT_ONLY" value="true" scope="default" type="STRING"/>
Namely :-
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file://D:/Tools</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file://D:/backup</parameter>
<parameter name="transport.vfs.FileNamePattern">.*.txt</parameter>
<parameter name="transport.vfs.ContentType">text/plain</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
Still no progress.
Can anyone help me here?
Regards,
Rahul.
In case anyone wants to know i have made a workaround for this i called a proxy service from my rest resource and it worked .
In my resource i called endpoint like this
<send>
<endpoint key="FileProxyEndPt"/>
</send>
Then i created a proxy service as follows
<proxy xmlns="http://ws.apache.org/ns/synapse" name="FileWriteProxy"
transports="http https vfs" startOnLoad="true" trace="enable">
<target>
<inSequence>
<clone>
<target sequence="FileWriteSequence" />
</clone>
</inSequence>
<outSequence />
<faultSequence />
</target>
<parameter name="transport.vfs.ActionAfterProcess">MOVE</parameter>
<parameter name="transport.vfs.MoveAfterProcess">file://D:/Tools</parameter>
<parameter name="transport.vfs.MoveAfterFailure">file://D:/backup</parameter>
<parameter name="transport.vfs.ContentType">text/plain; charset=ISO-8859-1</parameter>
<parameter name="transport.vfs.ActionAfterFailure">MOVE</parameter>
This way it worked it but never worked exactly in a resource.So had to take a longer route , hope somebody provides a solution which can be implemented directly.

Use Ant to find file with latest version number

I want to use ant to find the file with the latest version number. For example, I have a file directory named tomcat with the following files:
apache-tomcat-6.0.37.zip
apache-tomcat-6.0.38.zip
apache-tomcat-6.0.39.zip
I want ant to determine that apache-tomcat-6.0.39.zip is the latest file. Is there a way to do this?
Thanks!
Use resource collections, see last and sort. f.e. :
<project>
<path id="foo">
<last>
<sort>
<fileset dir="C:/some/path" includes="**/apache-tomcat-*.zip"/>
</sort>
</last>
</path>
<echo>$${foo} => ${toString:foo}</echo>
</project>
output :
[echo] ${foo} => C:\some\path\apache-tomcat-6.0.39.zip
use <pathconvert>to get file names from the relevant <fileset>.
use <sortlist> to sort the filenames in natural String order.
pick the last filename from the list.
try this:
<fileset dir="${your.base.dir}" id="one">
<include name="**/apache-tomcat-.*.zip"/>
</fileset>
<pathconvert property="orig.list" refid="one" pathsep=","/>
<sortlist property="sorted.list" value="${orig.list}" delimiter="," />
<propertyregex property="result" input="${sorted.list}" regexp=",?([^,]+?)$" select="\1"/>
inputList: <property name="one" value="a.b-2,a.b-5,a.b-1,a.b-3,a.b-4"/>
outputList: [echo] a.b-5

Example Databases

I am new to oracle. I wanted a huge sample database ( with a million tuples ) . I couldn't find any using google.
I'am using oracle 10g..
You guys know anywhere from where i can download?
Thank you ..
I don't know of any "ready-made" sample database of that size
As far as I can see, you have two options:
Use PolePosition to create a sample database. It's originally a benchmark frameworks but comes with it's own database schema and the necessary tools to generate a large database (you can define which size)
Use a test data generator like Benerator to completely create your test data from scratch. It seems a bit intimidating at first, but it's a really powerful tool. It also has generators to create meaningful names, zip codes and so on. So you'll get test data that "looks" real and doesn't contain gibberish.
The following benerator script generates a million rows for the table items and for each row in items it generates 10 rows in item_details (so you wind up with 1 million and 10 million rows)
<?xml version="1.0" encoding="iso-8859-1"?>
<setup xmlns="http://databene.org/benerator/0.7.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://databene.org/benerator/0.7.0 http://databene.org/benerator-0.7.0.xsd">
<import defaults="true"/>
<import platforms="csv"/>
<generate type="items" count="1000000">
<consumer class="org.databene.platform.csv.CSVEntityExporter">
<property name="uri" value="items.csv"/>
<property name="separator" value="|"/>
<property name="encoding" value="ISO-8859-1"/>
</consumer>
<id name="item_id" type="big_integer" generator="IncrementalIdGenerator"/>
<attribute name="item_name" type="string" pattern="[A-Z][a-z ]{6,25}"/>
<generate type="item_details" count="10">
<consumer class="org.databene.platform.csv.CSVEntityExporter">
<property name="uri" value="item_details.csv"/>
<property name="separator" value="|"/>
<property name="encoding" value="ISO-8859-1"/>
</consumer>
<id name="item_detail_id" type="big_integer" generator="IncrementalIdGenerator"/>
<attribute name="item_id" script="items.item_id"/>
<attribute name="sort_sequence" type="int" />
</generate>
</generate>
</setup>
If you want more "realistic" names, have a look a the following script which generates products with valid EAN Codes and some "normal" looking manufacturer names:
<?xml version="1.0" encoding="iso-8859-1"?>
<setup xmlns="http://databene.org/benerator/0.7.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://databene.org/benerator/0.7.0 http://databene.org/benerator-0.7.0.xsd">
<import platforms="csv"/>
<import domains="product"/>
<import domains="organization" />
<setting name="product_count" value="100000"/>
<generate type="product" count="{product_count}">
<consumer class="CSVEntityExporter">
<property name="uri" value="products.csv" />
<property name="separator" value=","/>
</consumer>
<id name="id" type="long"/>
<attribute name="ean_code" unique="true" generator="EANGenerator"/>
<attribute name="product_code" unique="true" pattern="[A-Z]{3}[0-9]{6}"/>
<variable name="cust" generator="CompanyNameGenerator" dataset="DE" locale="de_DE"/>
<attribute name="manufacturer_name" source="cust.shortName"/>
</generate>
</setup>
Once you have created the data files, you can use SQL*Loader to import them into the database.
This approach has the advantage that you have full control over the tables in your test database and you can tailor them to whatever you are trying to do with it.

Ant: How do I interate over all subfolders and perform a task in ant

Currently I do
<foreach list="${myfolders}" target="bundle"
param="worksheet" inheritall="true"/>
to execute the target "bundle" on a list of folders. However the problem is I need to set this list. How do I use Ant to just loop through all the folders given the parent directory?
If there is a way to do this and also exclude specific folders that would be even better. Thanks.
You can provide a <dirset> for the <foreach> task to operate on:
<foreach target="bundle" param="worksheet" inheritall="true">
<path>
<dirset dir="${subDir}">
<include name="*"/>
</dirset>
</path>
</foreach>
Notice that the list parameter isn't used when I do it this way.
You can't use <dirset> directly under the <foreach> as you can with <fileset>. However, you can put the <dirset> under the <path> as shown above. The <include name="*"/> prevents recursing down the directory tree.
You can do this with subant
Example:
<?xml version="1.0" encoding="UTF-8"?>
<project name="subant" default="subant1">
<target name="subant1">
<subant target="">
<dirset dir="." includes="*"/>
<target name="release" />
</subant>
</target>
</project>
I use the foreach task from ant-contrib for a similar job. This will call a specified target for each entry in a list, passing the entry as a parameter each time.

Resources