git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@269745 13f79535-47bb-0310-9956-ffa450edef68master
@@ -1,5 +1,5 @@ | |||||
Changes from Ant 1.4 to current CVS version | |||||
=========================================== | |||||
Changes from Ant 1.4.1 to current CVS version | |||||
============================================== | |||||
Changes that could break older environments: | Changes that could break older environments: | ||||
-------------------------------------------- | -------------------------------------------- | ||||
@@ -20,6 +20,49 @@ Fixed bugs: | |||||
* Fixed bug where ant would not copy system properties into new Project | * Fixed bug where ant would not copy system properties into new Project | ||||
in ant/antcall tasks when inheritall="false" is set. | in ant/antcall tasks when inheritall="false" is set. | ||||
Changes from Ant 1.4 to Ant 1.4.1 | |||||
=========================================== | |||||
Fixed bugs: | |||||
----------- | |||||
* <ant>'s antfile attribute will now also be considered an absolute path on | |||||
Windows systems, if it starts with a \ and no drive specifier. | |||||
* The fullpath attribute of <zipfileset> has been ignored if you used | |||||
the src attribute at the same time. | |||||
* The manifest file is now always placed as the second entry (after /META-INF) | |||||
in generated jars. This allows the manifest to be read by JarInputStreams | |||||
* Fixed bug in depend task which would fail with a NullPointerException if no | |||||
dependency cache was specified. | |||||
* sql task now handles REM statements correctly so that lines starying with rem | |||||
but which are not comments are actually processed. | |||||
* XMLLogger now uses the task's name rather than the classname | |||||
* <mapper>s will now work as expected if the to pattern expands to an | |||||
absolute pathname. | |||||
* <javac> didn't ignore memory settings in non-fork mode | |||||
* <cab> didn't split the options attribute into several command line | |||||
arguments correctly. | |||||
Other changes: | |||||
-------------- | |||||
* New source attribute for <javac> to enable assertion in JDK 1.4 | |||||
* XmlLogger and <antstructure> now add an encoding declaration to the | |||||
XML files they generate. | |||||
* <fileset> has a new attribute "casesensitive" to make it match | |||||
filenames in a case insensitive way (if you set it to false) - by | |||||
default filesets remain case sensitive. | |||||
Changes from Ant 1.3 to Ant 1.4 | Changes from Ant 1.3 to Ant 1.4 | ||||
=========================================== | =========================================== | ||||
@@ -185,7 +185,7 @@ task can be used to invoke them. It is best to specify that you want a | |||||
new JVM for these tests, so that a significant crash does not break the | new JVM for these tests, so that a significant crash does not break the | ||||
full build. The Junit extensions such as | full build. The Junit extensions such as | ||||
<a href="http://httpunit.sourceforge.net/">HttpUnit</a> for web pages, and | <a href="http://httpunit.sourceforge.net/">HttpUnit</a> for web pages, and | ||||
<a href="http://jakarta.apache.org/commons/cactus/">Cactus</a> for J2EE and servlet | |||||
<a href="http://jakarta.apache.org/cactus/">Cactus</a> for J2EE and servlet | |||||
testing help to expand the testing framework. To test properly you will still | testing help to expand the testing framework. To test properly you will still | ||||
need to invest a lot of effort in getting these to work with your project, and | need to invest a lot of effort in getting these to work with your project, and | ||||
deriving great unit, system and regression tests -but your customers will love | deriving great unit, system and regression tests -but your customers will love | ||||
@@ -659,10 +659,16 @@ Faster compiles with Jikes | |||||
</b><dd> | </b><dd> | ||||
The <a href="http://www.jikes.org/">jikes compiler</a> is usually much | The <a href="http://www.jikes.org/">jikes compiler</a> is usually much | ||||
faster than javac, and does dependency checking. Get it. Then set | |||||
build.compiler to "jikes" for it to be used in your build files. Better | |||||
yet, set the JIKES_HOME environment variable for jikes to automatically | |||||
get used, without changing your build files to only work with jikes. | |||||
faster than javac, does dependency checking and has better error | |||||
messages (usually). Get it. Then set | |||||
build.compiler to "jikes" for it to be used in your build files. | |||||
Doing this explicitly in your build files is a bit dubious as it requires the | |||||
whole team (and sub projects) to be using jikes too -something you can only | |||||
control in small, closed source projects. But if you set | |||||
<tt>ANT_OPTS = -Dbuild.compiler=jikes</tt> | |||||
in your environment, then all your builds on your system will use | |||||
Jikes automatically, while others can choose their own compiler, or let | |||||
ant choose whichever is appropriate for the current version of Java. | |||||
<dt><b> | <dt><b> | ||||
#include targets to simplify multi build.xml projects | #include targets to simplify multi build.xml projects | ||||
@@ -924,6 +930,25 @@ complicated. Use XML comments so that the file you wrote last month | |||||
still makes sense when you get back to it, and use Antidote to edit the | still makes sense when you get back to it, and use Antidote to edit the | ||||
files if you prefer it. | files if you prefer it. | ||||
<h3>Big projects still get complicated fast</h3> | |||||
Large software projects create their own complexity, with inter-dependent | |||||
libraries, long test cycles, hard deployment processes and a multitude of | |||||
people each working on their own bit of the solution. That's even before | |||||
the deadlines loom close, the integration problems become insurmountable, | |||||
weekends become indistinguishable from weekdays in terms of workload and | |||||
half the team stops talking to the other half. Ant may simplify the | |||||
build and test process, and can eliminate the full time 'makefile engineer' | |||||
role, but that doesn't mean that someone can stop 'owning the build'. | |||||
Being in charge of the build has to mean more than they type 'ant all' on | |||||
their system, it means they need to set the standards of what build tools to | |||||
use, what the common targets, what property names and files should be | |||||
and generally oversee the sub projects build processes. On a small project, | |||||
you don't need to do that -but remember: small projects become big projects | |||||
when you aren't looking. If you start off with a little bit of process, then | |||||
you can scale it if needed. Ff you start with none, by the time you need | |||||
it it will be too late. | |||||
<h3>You still need all the other foundational bits of a software | <h3>You still need all the other foundational bits of a software | ||||
project</h3> | project</h3> | ||||
@@ -988,4 +1013,4 @@ instead. | |||||
<hr> | <hr> | ||||
<p align="center">Copyright © 2000, 2001 Apache Software Foundation. All rights | <p align="center">Copyright © 2000, 2001 Apache Software Foundation. All rights | ||||
Reserved.</p> | Reserved.</p> | ||||
</body> | |||||
</body> |
@@ -166,7 +166,7 @@ the command line.</p> | |||||
<blockquote><pre> | <blockquote><pre> | ||||
<apply executable="somecommand" parallel="false" > | <apply executable="somecommand" parallel="false" > | ||||
<arg value="arg1"/> | <arg value="arg1"/> | ||||
<srfile/> | |||||
<srcfile/> | |||||
<arg value="arg2"/> | <arg value="arg2"/> | ||||
<fileset dir="/tmp"/> | <fileset dir="/tmp"/> | ||||
</apply> | </apply> | ||||
@@ -215,6 +215,15 @@ files/directories from the CLASSPATH it passes to the compiler.</p> | |||||
</td> | </td> | ||||
<td align="center" valign="top">No</td> | <td align="center" valign="top">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">source</td> | |||||
<td valign="top">Value of the <code>-source</code> command line | |||||
switch, will be ignored by all implementations except | |||||
<code>modern</code>, legal values are "1.3" and | |||||
"1.4" - by default, no <code>-source</code> argument | |||||
will be used at all.</td> | |||||
<td align="center" valign="top">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h3>Parameters specified as nested elements</h3> | <h3>Parameters specified as nested elements</h3> | ||||
@@ -291,15 +300,7 @@ or elements to filter for these packages. If you include part of your package-st | |||||
<h3>Jikes Notes</h3> | <h3>Jikes Notes</h3> | ||||
If the environment variable <tt>JIKES_HOME</tt> is set to the location | |||||
of the jikes compiler, then the standard Ant invocation scripts | |||||
automatically set build.compiler to "jikes". This enables one to use | |||||
jikes when available, without having to commit the build file to a | |||||
single choice of compiler. | |||||
<p> | |||||
Jikes also supports some extra options, which can be set be defining | |||||
Jikes supports some extra options, which can be set be defining | |||||
properties prior to invoking the task. The ant developers are aware that | properties prior to invoking the task. The ant developers are aware that | ||||
this is ugly and inflexible -expect a better solution in the future. All | this is ugly and inflexible -expect a better solution in the future. All | ||||
the options are boolean, and must be set to "true" or "yes" to be | the options are boolean, and must be set to "true" or "yes" to be | ||||
@@ -129,6 +129,12 @@ on the same schema.</p> | |||||
<td valign="top" align="center">Yes, unless statements enclosed within tags</td> | <td valign="top" align="center">Yes, unless statements enclosed within tags</td> | ||||
</tr> | </tr> | ||||
</table> | </table> | ||||
<h4>fileset</h4> | |||||
<p>You can specify multiple source files via nested <a | |||||
href="../CoreTypes/fileset.html">fileset</a> elements. Each file of | |||||
the fileset will be run in a transaction of its own, the order by | |||||
which the files of a single fileset will be executed is not | |||||
defined.</p> | |||||
<h4>classpath</h4> | <h4>classpath</h4> | ||||
<p><code>Sql</code>'s <em>classpath</em> attribute is a <a | <p><code>Sql</code>'s <em>classpath</em> attribute is a <a | ||||
href="../using.html#path">PATH like structure</a> and can also be set via a nested | href="../using.html#path">PATH like structure</a> and can also be set via a nested | ||||
@@ -205,6 +211,25 @@ operation on <i>some_other_table</i>.</p> | |||||
</sql> | </sql> | ||||
</pre></blockquote> | </pre></blockquote> | ||||
<p>The following example does the same as (and may execute additional | |||||
SQL files if there are more files matching the pattern | |||||
<code>data*.sql</code>) but doesn't guarantee that data1.sql will be | |||||
run before <code>data2.sql</code>.</p> | |||||
<blockquote><pre><sql | |||||
driver="org.database.jdbcDriver" | |||||
url="jdbc:database-url" | |||||
userid="sa" | |||||
password="pass" > | |||||
<fileset dir="."> | |||||
<include name="data*.sql" /> | |||||
</fileset> | |||||
<transaction> | |||||
truncate table some_other_table; | |||||
</transaction> | |||||
</sql> | |||||
</pre></blockquote> | |||||
<p>The following connects to the database given in url as the sa user using the | <p>The following connects to the database given in url as the sa user using the | ||||
org.database.jdbcDriver and executes the SQL statements contained within the | org.database.jdbcDriver and executes the SQL statements contained within the | ||||
file data.sql, with output piped to outputfile.txt, searching /some/jdbc.jar | file data.sql, with output piped to outputfile.txt, searching /some/jdbc.jar | ||||
@@ -62,11 +62,17 @@ attributes.</p> | |||||
taken to be an exclude pattern.</td> | taken to be an exclude pattern.</td> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">casesensitive</td> | |||||
<td valign="top">Must the file system be treated in a case sensitive way? | |||||
Defaults to true.</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<h4>Examples</h4> | <h4>Examples</h4> | ||||
<blockquote><pre> | <blockquote><pre> | ||||
<fileset dir="${server.src}" > | |||||
<fileset dir="${server.src}" casesensitive="yes" > | |||||
<patternset id="non.test.sources" > | <patternset id="non.test.sources" > | ||||
<include name="**/*.java"/> | <include name="**/*.java"/> | ||||
<exclude name="**/*Test*"/> | <exclude name="**/*Test*"/> | ||||
@@ -28,7 +28,7 @@ replacements in tasks like copy etc.<BR> | |||||
<TD vAlign=top align="center"><B>Required</B></TD> | <TD vAlign=top align="center"><B>Required</B></TD> | ||||
</TR> | </TR> | ||||
<TR> | <TR> | ||||
<TD vAlign=top>starttoken</TD> | |||||
<TD vAlign=top>begintoken</TD> | |||||
<TD vAlign=top>The string marking the beginning of a token. eg | <TD vAlign=top>The string marking the beginning of a token. eg | ||||
<STRONG>@</STRONG>Date@</TD> | <STRONG>@</STRONG>Date@</TD> | ||||
<TD vAlign=top>@</TD> | <TD vAlign=top>@</TD> | ||||
@@ -82,7 +82,7 @@ replacements in tasks like copy etc.<BR> | |||||
<p>You are copying the version.txt file to the dist directory from the build directory | <p>You are copying the version.txt file to the dist directory from the build directory | ||||
but wish to replace the token @DATE@ with todays date.</p> | but wish to replace the token @DATE@ with todays date.</p> | ||||
<BLOCKQUOTE><PRE> | <BLOCKQUOTE><PRE> | ||||
<copy file="${build.home}/version.txt" toFile="${dist.home}/version.txt"< | |||||
<copy file="${build.home}/version.txt" toFile="${dist.home}/version.txt"> | |||||
<filterset> | <filterset> | ||||
<filter token="DATE" value="${DATE}"/> | <filter token="DATE" value="${DATE}"/> | ||||
</filterset> | </filterset> | ||||
@@ -533,20 +533,6 @@ include: </p> | |||||
<li>TOPLink for WebLogic 2.5.1-enabled entity beans</li> | <li>TOPLink for WebLogic 2.5.1-enabled entity beans</li> | ||||
</ul> | </ul> | ||||
<p>This task supports two approaches to creating ejb jar files. The first | |||||
approach assumes a particular naming convention for deployment descriptor files. | |||||
For an Account bean, for example, the deployment descriptor would be named | |||||
<code>Account-ejb-jar.xml</code>. This naming convention allows the task to | |||||
distinguish deployment descriptors without relying on their positioning within a | |||||
source tree. It is also used to derive the name of the .jar file which is | |||||
generated. For the example this would be <code>Account.jar</code>. Vendor | |||||
specific files are assumed to be named in a similar fashion. The deployment | |||||
descriptor file which defines additional weblogic specific information for the | |||||
above bean would be <code>Account-weblogic-ejb-jar.xml</code>. The second | |||||
approach does not require a naming convention. This approach uses a specified a | |||||
jar name for the resultant ejb jar. If the jar name is present, then no naming | |||||
convention is required. If the jar name is not specified, then the default | |||||
naming convention is expected for the deployment descriptor files.</p> | |||||
<p>The task works as a directory scanning task, and performs an action for each | <p>The task works as a directory scanning task, and performs an action for each | ||||
deployment descriptor found. As such the includes and excludes should be set | deployment descriptor found. As such the includes and excludes should be set | ||||
@@ -571,6 +557,75 @@ respect to the class files and deployment descriptors that make up the bean. If | |||||
any of these files are newer than the jar file the jar will be rebuilt otherwise | any of these files are newer than the jar file the jar will be rebuilt otherwise | ||||
a message is logged that the jar file is up to date.</p> | a message is logged that the jar file is up to date.</p> | ||||
<h3>Naming Convention</h3> | |||||
Ejbjar handles the processing of multiple beans, and it uses a set of naming | |||||
conventions to determine the name of the generated EJB jars. The naming convention | |||||
that is used is controlled by the "naming" attribute. It supports the | |||||
following values | |||||
<ul> | |||||
<li>descriptor</li> | |||||
<p>This is the default naming scheme. The name of the generated bean is derived from the | |||||
name of the deployment descriptor. For an Account bean, for example, the deployment | |||||
descriptor would be named <code>Account-ejb-jar.xml</code>. Vendor specific descriptors are | |||||
located using the same naming convention. The weblogic bean, for example, would be named | |||||
<code>Account-weblogic-ejb-jar.xml</code>. Under this arrangment, the deployment descriptors | |||||
can be separated from the code implementing the beans, which can be useful whe the same bean code | |||||
is deployed in separate beans. | |||||
</p> | |||||
<p>This scheme is useful when you are using one bean per EJB jar and where you may be | |||||
deploying the same bean classes in different beans, with different deployment characteristics. | |||||
<li>ejb-name</li> | |||||
<p> This naming scheme uses the <ejb-name> element from the deployment descriptor to | |||||
determine the bean name. In this situation, the descriptors normally use the generic | |||||
descriptor names, such as <code>ejb-jar.xml</code> along with any associated vendor specific descriptor | |||||
names. For example, If the value of the <ejb-name> were to be given in the deployment descriptor | |||||
as follows: | |||||
<pre> | |||||
<ejb-jar> | |||||
<enterprise-beans> | |||||
<entity> | |||||
<ejb-name>Sample</ejb-name> | |||||
<home>org.apache.ant.ejbsample.SampleHome</home> | |||||
</pre> | |||||
then the name of the generated bean would be <code>Sample.jar</code> | |||||
</p> | |||||
<p> This scheme is useful where you want to use the standard deployment descriptor names, which may be more | |||||
compatible with other EJB tools. This scheme must have one bean per jar. | |||||
</p> | |||||
<li>directory</li> | |||||
<p> | |||||
In this mode, the name of the generated bean jar is derived from the directory | |||||
containing the deployment descriptors. Again the deployment descriptors typically use | |||||
the standard filenames. For example, if the path to the deployment descriptor is | |||||
<code>/home/user/dev/appserver/dd/sample</code>, then the generated | |||||
bean will be named <code>sample.jar</code> | |||||
</p> | |||||
<p> | |||||
This scheme is also useful when you want to use standard style descriptor names. It is often | |||||
most useful when the descriptors are located in the same directory as the bean source code, | |||||
although that is not mandatory. This scheme can handle multiple beans per jar. | |||||
</p> | |||||
<li>basejarname</li> | |||||
<p> | |||||
The final scheme supported by the <ejbjar> task is used when you want to specify the generated | |||||
bean jar name directly. In this case the name of the generated jar is specified by the | |||||
"basejarname" attribute. Since all generated beans will have the same name, this task should | |||||
be only used when each descriptor is in its own directory. | |||||
</p> | |||||
<p> | |||||
This scheme is most appropriate when you are using multiple beans per jar and only process a single | |||||
deployment descriptor. You typically want to specify the name of the jar and not derive it from the | |||||
beans in the jar. | |||||
</p> | |||||
</ul> | |||||
<h3>Parameters:</h3> | <h3>Parameters:</h3> | ||||
<table border="1" cellpadding="2" cellspacing="0"> | <table border="1" cellpadding="2" cellspacing="0"> | ||||
<tr> | <tr> | ||||
@@ -605,6 +660,12 @@ a message is logged that the jar file is up to date.</p> | |||||
deployment elements have been specified).</td> | deployment elements have been specified).</td> | ||||
<td valign="top" align="center">Yes</td> | <td valign="top" align="center">Yes</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td valign="top">naming</td> | |||||
<td valign="top">Controls the naming convention used to name generated | |||||
EJB jars. Please refer to the description above.</td> | |||||
<td valign="top" align="center">No</td> | |||||
</tr> | |||||
<tr> | <tr> | ||||
<td valign="top">basejarname</td> | <td valign="top">basejarname</td> | ||||
<td valign="top">The base name that is used for the generated jar files. | <td valign="top">The base name that is used for the generated jar files. | ||||
@@ -1,14 +0,0 @@ | |||||
<?xml version="1.0"?> | |||||
<project name="xxx-test" basedir="." default="test1"> | |||||
<target name="test1"> | |||||
</target> | |||||
<target name="test2"> | |||||
</target> | |||||
<target name="test3"> | |||||
</target> | |||||
</project> |
@@ -113,6 +113,9 @@ import java.util.*; | |||||
* "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where | * "**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where | ||||
* there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123"). | * there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123"). | ||||
* <p> | * <p> | ||||
* Case sensitivity may be turned off if necessary. By default, it is | |||||
* turned on. | |||||
* <p> | |||||
* Example of usage: | * Example of usage: | ||||
* <pre> | * <pre> | ||||
* String[] includes = {"**\\*.class"}; | * String[] includes = {"**\\*.class"}; | ||||
@@ -120,6 +123,7 @@ import java.util.*; | |||||
* ds.setIncludes(includes); | * ds.setIncludes(includes); | ||||
* ds.setExcludes(excludes); | * ds.setExcludes(excludes); | ||||
* ds.setBasedir(new File("test")); | * ds.setBasedir(new File("test")); | ||||
* ds.setCaseSensitive(true); | |||||
* ds.scan(); | * ds.scan(); | ||||
* | * | ||||
* System.out.println("FILES:"); | * System.out.println("FILES:"); | ||||
@@ -132,6 +136,7 @@ import java.util.*; | |||||
* .class files in all directories under a directory called "modules" | * .class files in all directories under a directory called "modules" | ||||
* | * | ||||
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> | * @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a> | ||||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||||
*/ | */ | ||||
public class DirectoryScanner implements FileScanner { | public class DirectoryScanner implements FileScanner { | ||||
@@ -207,6 +212,11 @@ public class DirectoryScanner implements FileScanner { | |||||
*/ | */ | ||||
protected boolean haveSlowResults = false; | protected boolean haveSlowResults = false; | ||||
/** | |||||
* Should the file system be treated as a case sensitive one? | |||||
*/ | |||||
protected boolean isCaseSensitive = true; | |||||
/** | /** | ||||
* Constructor. | * Constructor. | ||||
*/ | */ | ||||
@@ -216,7 +226,7 @@ public class DirectoryScanner implements FileScanner { | |||||
/** | /** | ||||
* Does the path match the start of this pattern up to the first "**". | * Does the path match the start of this pattern up to the first "**". | ||||
+ | |||||
* | |||||
* <p>This is not a general purpose test and should only be used if you | * <p>This is not a general purpose test and should only be used if you | ||||
* can live with false positives.</p> | * can live with false positives.</p> | ||||
* | * | ||||
@@ -226,6 +236,23 @@ public class DirectoryScanner implements FileScanner { | |||||
* @param str the (non-null) string (path) to match | * @param str the (non-null) string (path) to match | ||||
*/ | */ | ||||
protected static boolean matchPatternStart(String pattern, String str) { | protected static boolean matchPatternStart(String pattern, String str) { | ||||
return matchPatternStart(pattern, str, true); | |||||
} | |||||
/** | |||||
* Does the path match the start of this pattern up to the first "**". | |||||
* | |||||
* <p>This is not a general purpose test and should only be used if you | |||||
* can live with false positives.</p> | |||||
* | |||||
* <p><code>pattern=**\\a</code> and <code>str=b</code> will yield true. | |||||
* | |||||
* @param pattern the (non-null) pattern to match against | |||||
* @param str the (non-null) string (path) to match | |||||
* @param isCaseSensitive must matches be case sensitive? | |||||
*/ | |||||
protected static boolean matchPatternStart(String pattern, String str, | |||||
boolean isCaseSensitive) { | |||||
// When str starts with a File.separator, pattern has to start with a | // When str starts with a File.separator, pattern has to start with a | ||||
// File.separator. | // File.separator. | ||||
// When pattern starts with a File.separator, str has to start with a | // When pattern starts with a File.separator, str has to start with a | ||||
@@ -258,7 +285,7 @@ public class DirectoryScanner implements FileScanner { | |||||
if (patDir.equals("**")) { | if (patDir.equals("**")) { | ||||
break; | break; | ||||
} | } | ||||
if (!match(patDir,(String)strDirs.elementAt(strIdxStart))) { | |||||
if (!match(patDir,(String)strDirs.elementAt(strIdxStart), isCaseSensitive)) { | |||||
return false; | return false; | ||||
} | } | ||||
patIdxStart++; | patIdxStart++; | ||||
@@ -288,6 +315,20 @@ public class DirectoryScanner implements FileScanner { | |||||
* <code>false</code> otherwise. | * <code>false</code> otherwise. | ||||
*/ | */ | ||||
protected static boolean matchPath(String pattern, String str) { | protected static boolean matchPath(String pattern, String str) { | ||||
return matchPath(pattern, str, true); | |||||
} | |||||
/** | |||||
* Matches a path against a pattern. | |||||
* | |||||
* @param pattern the (non-null) pattern to match against | |||||
* @param str the (non-null) string (path) to match | |||||
* @param isCaseSensitive must a case sensitive match be done? | |||||
* | |||||
* @return <code>true</code> when the pattern matches against the string. | |||||
* <code>false</code> otherwise. | |||||
*/ | |||||
protected static boolean matchPath(String pattern, String str, boolean isCaseSensitive) { | |||||
// When str starts with a File.separator, pattern has to start with a | // When str starts with a File.separator, pattern has to start with a | ||||
// File.separator. | // File.separator. | ||||
// When pattern starts with a File.separator, str has to start with a | // When pattern starts with a File.separator, str has to start with a | ||||
@@ -320,7 +361,7 @@ public class DirectoryScanner implements FileScanner { | |||||
if (patDir.equals("**")) { | if (patDir.equals("**")) { | ||||
break; | break; | ||||
} | } | ||||
if (!match(patDir,(String)strDirs.elementAt(strIdxStart))) { | |||||
if (!match(patDir,(String)strDirs.elementAt(strIdxStart), isCaseSensitive)) { | |||||
return false; | return false; | ||||
} | } | ||||
patIdxStart++; | patIdxStart++; | ||||
@@ -347,7 +388,7 @@ public class DirectoryScanner implements FileScanner { | |||||
if (patDir.equals("**")) { | if (patDir.equals("**")) { | ||||
break; | break; | ||||
} | } | ||||
if (!match(patDir,(String)strDirs.elementAt(strIdxEnd))) { | |||||
if (!match(patDir,(String)strDirs.elementAt(strIdxEnd), isCaseSensitive)) { | |||||
return false; | return false; | ||||
} | } | ||||
patIdxEnd--; | patIdxEnd--; | ||||
@@ -386,7 +427,7 @@ strLoop: | |||||
for (int j = 0; j < patLength; j++) { | for (int j = 0; j < patLength; j++) { | ||||
String subPat = (String)patDirs.elementAt(patIdxStart+j+1); | String subPat = (String)patDirs.elementAt(patIdxStart+j+1); | ||||
String subStr = (String)strDirs.elementAt(strIdxStart+i+j); | String subStr = (String)strDirs.elementAt(strIdxStart+i+j); | ||||
if (!match(subPat,subStr)) { | |||||
if (!match(subPat,subStr, isCaseSensitive)) { | |||||
continue strLoop; | continue strLoop; | ||||
} | } | ||||
} | } | ||||
@@ -413,7 +454,6 @@ strLoop: | |||||
} | } | ||||
/** | /** | ||||
* Matches a string against a pattern. The pattern contains two special | * Matches a string against a pattern. The pattern contains two special | ||||
* characters: | * characters: | ||||
@@ -428,6 +468,24 @@ strLoop: | |||||
* <code>false</code> otherwise. | * <code>false</code> otherwise. | ||||
*/ | */ | ||||
protected static boolean match(String pattern, String str) { | protected static boolean match(String pattern, String str) { | ||||
return match(pattern, str, true); | |||||
} | |||||
/** | |||||
* Matches a string against a pattern. The pattern contains two special | |||||
* characters: | |||||
* '*' which means zero or more characters, | |||||
* '?' which means one and only one character. | |||||
* | |||||
* @param pattern the (non-null) pattern to match against | |||||
* @param str the (non-null) string that must be matched against the | |||||
* pattern | |||||
* | |||||
* @return <code>true</code> when the string matches against the pattern, | |||||
* <code>false</code> otherwise. | |||||
*/ | |||||
protected static boolean match(String pattern, String str, boolean isCaseSensitive) { | |||||
char[] patArr = pattern.toCharArray(); | char[] patArr = pattern.toCharArray(); | ||||
char[] strArr = str.toCharArray(); | char[] strArr = str.toCharArray(); | ||||
int patIdxStart = 0; | int patIdxStart = 0; | ||||
@@ -451,21 +509,33 @@ strLoop: | |||||
} | } | ||||
for (int i = 0; i <= patIdxEnd; i++) { | for (int i = 0; i <= patIdxEnd; i++) { | ||||
ch = patArr[i]; | ch = patArr[i]; | ||||
if (ch != '?' && ch != strArr[i]) { | |||||
return false; // Character mismatch | |||||
if (ch != '?') { | |||||
if (isCaseSensitive && ch != strArr[i]) { | |||||
return false;// Character mismatch | |||||
} | |||||
if (!isCaseSensitive && Character.toUpperCase(ch) != | |||||
Character.toUpperCase(strArr[i])) { | |||||
return false; // Character mismatch | |||||
} | |||||
} | } | ||||
} | } | ||||
return true; // String matches against pattern | return true; // String matches against pattern | ||||
} | } | ||||
if (patIdxEnd == 0) { | if (patIdxEnd == 0) { | ||||
return true; // Pattern contains only '*', which matches anything | return true; // Pattern contains only '*', which matches anything | ||||
} | } | ||||
// Process characters before first star | // Process characters before first star | ||||
while((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { | while((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) { | ||||
if (ch != '?' && ch != strArr[strIdxStart]) { | |||||
return false; | |||||
if (ch != '?') { | |||||
if (isCaseSensitive && ch != strArr[strIdxStart]) { | |||||
return false;// Character mismatch | |||||
} | |||||
if (!isCaseSensitive && Character.toUpperCase(ch) != | |||||
Character.toUpperCase(strArr[strIdxStart])) { | |||||
return false;// Character mismatch | |||||
} | |||||
} | } | ||||
patIdxStart++; | patIdxStart++; | ||||
strIdxStart++; | strIdxStart++; | ||||
@@ -483,8 +553,14 @@ strLoop: | |||||
// Process characters after last star | // Process characters after last star | ||||
while((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { | while((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) { | ||||
if (ch != '?' && ch != strArr[strIdxEnd]) { | |||||
return false; | |||||
if (ch != '?') { | |||||
if (isCaseSensitive && ch != strArr[strIdxEnd]) { | |||||
return false;// Character mismatch | |||||
} | |||||
if (!isCaseSensitive && Character.toUpperCase(ch) != | |||||
Character.toUpperCase(strArr[strIdxEnd])) { | |||||
return false;// Character mismatch | |||||
} | |||||
} | } | ||||
patIdxEnd--; | patIdxEnd--; | ||||
strIdxEnd--; | strIdxEnd--; | ||||
@@ -520,12 +596,18 @@ strLoop: | |||||
int patLength = (patIdxTmp-patIdxStart-1); | int patLength = (patIdxTmp-patIdxStart-1); | ||||
int strLength = (strIdxEnd-strIdxStart+1); | int strLength = (strIdxEnd-strIdxStart+1); | ||||
int foundIdx = -1; | int foundIdx = -1; | ||||
strLoop: | |||||
strLoop: | |||||
for (int i = 0; i <= strLength - patLength; i++) { | for (int i = 0; i <= strLength - patLength; i++) { | ||||
for (int j = 0; j < patLength; j++) { | for (int j = 0; j < patLength; j++) { | ||||
ch = patArr[patIdxStart+j+1]; | ch = patArr[patIdxStart+j+1]; | ||||
if (ch != '?' && ch != strArr[strIdxStart+i+j]) { | |||||
continue strLoop; | |||||
if (ch != '?') { | |||||
if (isCaseSensitive && ch != strArr[strIdxStart+i+j]) { | |||||
continue strLoop; | |||||
} | |||||
if (!isCaseSensitive && Character.toUpperCase(ch) != | |||||
Character.toUpperCase(strArr[strIdxStart+i+j])) { | |||||
continue strLoop; | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -591,6 +673,15 @@ strLoop: | |||||
/** | |||||
* Sets the case sensitivity of the file system | |||||
* | |||||
* @param specifies if the filesystem is case sensitive | |||||
*/ | |||||
public void setCaseSensitive(boolean isCaseSensitive) { | |||||
this.isCaseSensitive = isCaseSensitive; | |||||
} | |||||
/** | /** | ||||
* Sets the set of include patterns to use. All '/' and '\' characters are | * Sets the set of include patterns to use. All '/' and '\' characters are | ||||
* replaced by <code>File.separatorChar</code>. So the separator used need | * replaced by <code>File.separatorChar</code>. So the separator used need | ||||
@@ -808,7 +899,7 @@ strLoop: | |||||
*/ | */ | ||||
protected boolean isIncluded(String name) { | protected boolean isIncluded(String name) { | ||||
for (int i = 0; i < includes.length; i++) { | for (int i = 0; i < includes.length; i++) { | ||||
if (matchPath(includes[i],name)) { | |||||
if (matchPath(includes[i],name, isCaseSensitive)) { | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
@@ -824,7 +915,7 @@ strLoop: | |||||
*/ | */ | ||||
protected boolean couldHoldIncluded(String name) { | protected boolean couldHoldIncluded(String name) { | ||||
for (int i = 0; i < includes.length; i++) { | for (int i = 0; i < includes.length; i++) { | ||||
if (matchPatternStart(includes[i],name)) { | |||||
if (matchPatternStart(includes[i],name, isCaseSensitive)) { | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
@@ -840,7 +931,7 @@ strLoop: | |||||
*/ | */ | ||||
protected boolean isExcluded(String name) { | protected boolean isExcluded(String name) { | ||||
for (int i = 0; i < excludes.length; i++) { | for (int i = 0; i < excludes.length; i++) { | ||||
if (matchPath(excludes[i],name)) { | |||||
if (matchPath(excludes[i],name, isCaseSensitive)) { | |||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
@@ -152,4 +152,11 @@ public interface FileScanner { | |||||
* @param includes list of include patterns | * @param includes list of include patterns | ||||
*/ | */ | ||||
void setIncludes(String[] includes); | void setIncludes(String[] includes); | ||||
/** | |||||
* Sets the case sensitivity of the file system | |||||
* | |||||
* @param specifies if the filesystem is case sensitive | |||||
*/ | |||||
void setCaseSensitive(boolean isCaseSensitive); | |||||
} | } |
@@ -421,11 +421,7 @@ public class ProjectHelper { | |||||
// take care of dependencies | // take care of dependencies | ||||
if (depends.length() > 0) { | if (depends.length() > 0) { | ||||
StringTokenizer tok = | |||||
new StringTokenizer(depends, ",", false); | |||||
while (tok.hasMoreTokens()) { | |||||
target.addDependency(tok.nextToken().trim()); | |||||
} | |||||
target.setDepends(depends); | |||||
} | } | ||||
} | } | ||||
@@ -85,7 +85,10 @@ public class Target implements TaskContainer { | |||||
StringTokenizer tok = | StringTokenizer tok = | ||||
new StringTokenizer(depS, ",", false); | new StringTokenizer(depS, ",", false); | ||||
while (tok.hasMoreTokens()) { | while (tok.hasMoreTokens()) { | ||||
addDependency(tok.nextToken().trim()); | |||||
String token = tok.nextToken().trim(); | |||||
if (!token.equals("")) { | |||||
addDependency(token); | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -201,11 +201,7 @@ public class XmlLogger implements BuildListener { | |||||
taskElement.startTime = System.currentTimeMillis(); | taskElement.startTime = System.currentTimeMillis(); | ||||
taskElement.element = doc.createElement(TASK_TAG); | taskElement.element = doc.createElement(TASK_TAG); | ||||
String name = task.getClass().getName(); | |||||
int pos = name.lastIndexOf("."); | |||||
if (pos != -1) { | |||||
name = name.substring(pos + 1); | |||||
} | |||||
String name = event.getTask().getTaskName(); | |||||
taskElement.element.setAttribute(NAME_ATTR, name); | taskElement.element.setAttribute(NAME_ATTR, name); | ||||
taskElement.element.setAttribute(LOCATION_ATTR, event.getTask().getLocation().toString()); | taskElement.element.setAttribute(LOCATION_ATTR, event.getTask().getLocation().toString()); | ||||
tasks.put(task, taskElement); | tasks.put(task, taskElement); | ||||
@@ -80,28 +80,40 @@ import java.util.*; | |||||
*/ | */ | ||||
public class Ant extends Task { | public class Ant extends Task { | ||||
/** the basedir where is executed the build file */ | |||||
private File dir = null; | private File dir = null; | ||||
/** the build.xml file (can be absolute) in this case dir will be ignored */ | |||||
private String antFile = null; | private String antFile = null; | ||||
/** the target to call if any */ | |||||
private String target = null; | private String target = null; | ||||
/** the output */ | |||||
private String output = null; | private String output = null; | ||||
/** should we inherit properties from the parent ? */ | |||||
private boolean inheritAll = true; | private boolean inheritAll = true; | ||||
Vector properties = new Vector(); | |||||
Project p1; | |||||
/** the properties to pass to the new project */ | |||||
private Vector properties = new Vector(); | |||||
/** the temporary project created to run the build file */ | |||||
private Project newProject; | |||||
/** | /** | ||||
* If true, inherit all properties from parent Project | * If true, inherit all properties from parent Project | ||||
* If false, inherit only userProperties and those defined | * If false, inherit only userProperties and those defined | ||||
* inside the ant call itself | * inside the ant call itself | ||||
**/ | |||||
public void setInheritAll(boolean inherit) { | |||||
inheritAll = inherit; | |||||
} //-- setInheritAll | |||||
*/ | |||||
public void setInheritAll(boolean value) { | |||||
inheritAll = value; | |||||
} | |||||
public void init() { | public void init() { | ||||
p1 = new Project(); | |||||
p1.setJavaVersionProperty(); | |||||
p1.addTaskDefinition("property", | |||||
newProject = new Project(); | |||||
newProject.setJavaVersionProperty(); | |||||
newProject.addTaskDefinition("property", | |||||
(Class)project.getTaskDefinitions().get("property")); | (Class)project.getTaskDefinitions().get("property")); | ||||
} | } | ||||
@@ -109,7 +121,7 @@ public class Ant extends Task { | |||||
init(); | init(); | ||||
for (int i=0; i<properties.size(); i++) { | for (int i=0; i<properties.size(); i++) { | ||||
Property p = (Property) properties.elementAt(i); | Property p = (Property) properties.elementAt(i); | ||||
Property newP = (Property) p1.createTask("property"); | |||||
Property newP = (Property) newProject.createTask("property"); | |||||
newP.setName(p.getName()); | newP.setName(p.getName()); | ||||
if (p.getValue() != null) { | if (p.getValue() != null) { | ||||
newP.setValue(p.getValue()); | newP.setValue(p.getValue()); | ||||
@@ -127,7 +139,7 @@ public class Ant extends Task { | |||||
private void initializeProject() { | private void initializeProject() { | ||||
Vector listeners = project.getBuildListeners(); | Vector listeners = project.getBuildListeners(); | ||||
for (int i = 0; i < listeners.size(); i++) { | for (int i = 0; i < listeners.size(); i++) { | ||||
p1.addBuildListener((BuildListener)listeners.elementAt(i)); | |||||
newProject.addBuildListener((BuildListener)listeners.elementAt(i)); | |||||
} | } | ||||
if (output != null) { | if (output != null) { | ||||
@@ -137,7 +149,7 @@ public class Ant extends Task { | |||||
logger.setMessageOutputLevel(Project.MSG_INFO); | logger.setMessageOutputLevel(Project.MSG_INFO); | ||||
logger.setOutputPrintStream(out); | logger.setOutputPrintStream(out); | ||||
logger.setErrorPrintStream(out); | logger.setErrorPrintStream(out); | ||||
p1.addBuildListener(logger); | |||||
newProject.addBuildListener(logger); | |||||
} | } | ||||
catch( IOException ex ) { | catch( IOException ex ) { | ||||
log( "Ant: Can't set output to " + output ); | log( "Ant: Can't set output to " + output ); | ||||
@@ -149,7 +161,7 @@ public class Ant extends Task { | |||||
while (et.hasMoreElements()) { | while (et.hasMoreElements()) { | ||||
String taskName = (String) et.nextElement(); | String taskName = (String) et.nextElement(); | ||||
Class taskClass = (Class) taskdefs.get(taskName); | Class taskClass = (Class) taskdefs.get(taskName); | ||||
p1.addTaskDefinition(taskName, taskClass); | |||||
newProject.addTaskDefinition(taskName, taskClass); | |||||
} | } | ||||
Hashtable typedefs = project.getDataTypeDefinitions(); | Hashtable typedefs = project.getDataTypeDefinitions(); | ||||
@@ -157,7 +169,7 @@ public class Ant extends Task { | |||||
while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
String typeName = (String) e.nextElement(); | String typeName = (String) e.nextElement(); | ||||
Class typeClass = (Class) typedefs.get(typeName); | Class typeClass = (Class) typedefs.get(typeName); | ||||
p1.addDataTypeDefinition(typeName, typeClass); | |||||
newProject.addDataTypeDefinition(typeName, typeClass); | |||||
} | } | ||||
// set user-defined or all properties from calling project | // set user-defined or all properties from calling project | ||||
@@ -170,23 +182,24 @@ public class Ant extends Task { | |||||
// set Java built-in properties separately, | // set Java built-in properties separately, | ||||
// b/c we won't inherit them. | // b/c we won't inherit them. | ||||
p1.setSystemProperties(); | |||||
newProject.setSystemProperties(); | |||||
} | } | ||||
e = prop1.keys(); | e = prop1.keys(); | ||||
while (e.hasMoreElements()) { | while (e.hasMoreElements()) { | ||||
String arg = (String) e.nextElement(); | String arg = (String) e.nextElement(); | ||||
String value = (String) prop1.get(arg); | String value = (String) prop1.get(arg); | ||||
if (inheritAll == true) | |||||
p1.setProperty(arg, value); | |||||
else | |||||
p1.setUserProperty(arg, value); | |||||
if (inheritAll == true){ | |||||
newProject.setProperty(arg, value); | |||||
} else { | |||||
newProject.setUserProperty(arg, value); | |||||
} | |||||
} | } | ||||
} | } | ||||
protected void handleOutput(String line) { | protected void handleOutput(String line) { | ||||
if (p1 != null) { | |||||
p1.demuxOutput(line, false); | |||||
if (newProject != null) { | |||||
newProject.demuxOutput(line, false); | |||||
} | } | ||||
else { | else { | ||||
super.handleOutput(line); | super.handleOutput(line); | ||||
@@ -194,8 +207,8 @@ public class Ant extends Task { | |||||
} | } | ||||
protected void handleErrorOutput(String line) { | protected void handleErrorOutput(String line) { | ||||
if (p1 != null) { | |||||
p1.demuxOutput(line, true); | |||||
if (newProject != null) { | |||||
newProject.demuxOutput(line, true); | |||||
} | } | ||||
else { | else { | ||||
super.handleErrorOutput(line); | super.handleErrorOutput(line); | ||||
@@ -207,17 +220,18 @@ public class Ant extends Task { | |||||
*/ | */ | ||||
public void execute() throws BuildException { | public void execute() throws BuildException { | ||||
try { | try { | ||||
if (p1 == null) { | |||||
if (newProject == null) { | |||||
reinit(); | reinit(); | ||||
} | } | ||||
if(dir == null) | |||||
if (dir == null) { | |||||
dir = project.getBaseDir(); | dir = project.getBaseDir(); | ||||
} | |||||
initializeProject(); | initializeProject(); | ||||
p1.setBaseDir(dir); | |||||
p1.setUserProperty("basedir" , dir.getAbsolutePath()); | |||||
newProject.setBaseDir(dir); | |||||
newProject.setUserProperty("basedir" , dir.getAbsolutePath()); | |||||
// Override with local-defined properties | // Override with local-defined properties | ||||
Enumeration e = properties.elements(); | Enumeration e = properties.elements(); | ||||
@@ -226,43 +240,59 @@ public class Ant extends Task { | |||||
p.execute(); | p.execute(); | ||||
} | } | ||||
if (antFile == null) | |||||
if (antFile == null) { | |||||
antFile = "build.xml"; | antFile = "build.xml"; | ||||
} | |||||
File file = FileUtils.newFileUtils().resolveFile(dir, antFile); | File file = FileUtils.newFileUtils().resolveFile(dir, antFile); | ||||
antFile = file.getAbsolutePath(); | antFile = file.getAbsolutePath(); | ||||
p1.setUserProperty( "ant.file" , antFile ); | |||||
ProjectHelper.configureProject(p1, new File(antFile)); | |||||
newProject.setUserProperty( "ant.file" , antFile ); | |||||
ProjectHelper.configureProject(newProject, new File(antFile)); | |||||
if (target == null) { | if (target == null) { | ||||
target = p1.getDefaultTarget(); | |||||
target = newProject.getDefaultTarget(); | |||||
} | } | ||||
// Are we trying to call the target in which we are defined? | // Are we trying to call the target in which we are defined? | ||||
if (p1.getBaseDir().equals(project.getBaseDir()) && | |||||
p1.getProperty("ant.file").equals(project.getProperty("ant.file")) && | |||||
if (newProject.getBaseDir().equals(project.getBaseDir()) && | |||||
newProject.getProperty("ant.file").equals(project.getProperty("ant.file")) && | |||||
getOwningTarget() != null && | getOwningTarget() != null && | ||||
target.equals(this.getOwningTarget().getName())) { | target.equals(this.getOwningTarget().getName())) { | ||||
throw new BuildException("ant task calling its own parent target"); | throw new BuildException("ant task calling its own parent target"); | ||||
} | } | ||||
p1.executeTarget(target); | |||||
newProject.executeTarget(target); | |||||
} finally { | } finally { | ||||
// help the gc | // help the gc | ||||
p1 = null; | |||||
newProject = null; | |||||
} | } | ||||
} | } | ||||
/** | |||||
* ... | |||||
*/ | |||||
public void setDir(File d) { | public void setDir(File d) { | ||||
this.dir = d; | this.dir = d; | ||||
} | } | ||||
/** | |||||
* set the build file, it can be either absolute or relative. | |||||
* If it is absolute, <tt>dir</tt> will be ignored, if it is | |||||
* relative it will be resolved relative to <tt>dir</tt>. | |||||
*/ | |||||
public void setAntfile(String s) { | public void setAntfile(String s) { | ||||
// @note: it is a string and not a file to handle relative/absolute | |||||
// otherwise a relative file will be resolved based on the current | |||||
// basedir. | |||||
this.antFile = s; | this.antFile = s; | ||||
} | } | ||||
/** | |||||
* set the target to execute. If none is defined it will | |||||
* execute the default target of the build file | |||||
*/ | |||||
public void setTarget(String s) { | public void setTarget(String s) { | ||||
this.target = s; | this.target = s; | ||||
} | } | ||||
@@ -271,12 +301,12 @@ public class Ant extends Task { | |||||
this.output = s; | this.output = s; | ||||
} | } | ||||
/** create a property to pass to the new project as a 'user property' */ | |||||
public Property createProperty() { | public Property createProperty() { | ||||
if (p1 == null) { | |||||
if (newProject == null) { | |||||
reinit(); | reinit(); | ||||
} | } | ||||
Property p=(Property)p1.createTask("property"); | |||||
Property p=(Property)newProject.createTask("property"); | |||||
p.setUserProperty(true); | p.setUserProperty(true); | ||||
properties.addElement( p ); | properties.addElement( p ); | ||||
return p; | return p; | ||||
@@ -146,7 +146,7 @@ public class AntStructure extends Task { | |||||
private void printHead(PrintWriter out, Enumeration tasks, | private void printHead(PrintWriter out, Enumeration tasks, | ||||
Enumeration types) { | Enumeration types) { | ||||
out.println("<?xml version=\"1.0\" ?>"); | |||||
out.println("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"); | |||||
out.println("<!ENTITY % boolean \"(true|false|on|off|yes|no)\">"); | out.println("<!ENTITY % boolean \"(true|false|on|off|yes|no)\">"); | ||||
out.print("<!ENTITY % tasks \""); | out.print("<!ENTITY % tasks \""); | ||||
boolean first = true; | boolean first = true; | ||||
@@ -141,20 +141,29 @@ public class Jar extends Zip { | |||||
throws IOException, BuildException | throws IOException, BuildException | ||||
{ | { | ||||
try { | try { | ||||
// If no manifest is specified, add the default one. | |||||
if (manifest == null) { | |||||
execManifest = null; | |||||
} | |||||
else { | |||||
execManifest = new Manifest(); | |||||
execManifest = getDefaultManifest(); | |||||
if (manifest != null) { | |||||
execManifest.merge(manifest); | execManifest.merge(manifest); | ||||
} | } | ||||
for (Enumeration e = execManifest.getWarnings(); e.hasMoreElements(); ) { | |||||
log("Manifest warning: " + (String)e.nextElement(), Project.MSG_WARN); | |||||
} | |||||
zipDir(null, zOut, "META-INF/"); | zipDir(null, zOut, "META-INF/"); | ||||
// time to write the manifest | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
PrintWriter writer = new PrintWriter(baos); | |||||
execManifest.write(writer); | |||||
writer.flush(); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | |||||
super.initZipOutputStream(zOut); | super.initZipOutputStream(zOut); | ||||
} | } | ||||
catch (ManifestException e) { | catch (ManifestException e) { | ||||
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR); | |||||
throw new BuildException("Invalid Manifest", e, getLocation()); | |||||
log("Manifest is invalid: " + e.getMessage(), Project.MSG_ERR); | |||||
throw new BuildException("Invalid Manifest", e, getLocation()); | |||||
} | } | ||||
} | } | ||||
@@ -175,28 +184,6 @@ public class Jar extends Zip { | |||||
} | } | ||||
} | } | ||||
protected void finalizeZipOutputStream(ZipOutputStream zOut) | |||||
throws IOException, BuildException { | |||||
if (execManifest == null) { | |||||
execManifest = getDefaultManifest(); | |||||
} | |||||
for (Enumeration e = execManifest.getWarnings(); e.hasMoreElements(); ) { | |||||
log("Manifest warning: " + (String)e.nextElement(), Project.MSG_WARN); | |||||
} | |||||
// time to write the manifest | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
PrintWriter writer = new PrintWriter(baos); | |||||
execManifest.write(writer); | |||||
writer.flush(); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
super.zipFile(bais, zOut, "META-INF/MANIFEST.MF", System.currentTimeMillis()); | |||||
super.finalizeZipOutputStream(zOut); | |||||
} | |||||
/** | /** | ||||
* Handle situation when we encounter a manifest file | * Handle situation when we encounter a manifest file | ||||
* | * | ||||
@@ -223,30 +210,17 @@ public class Jar extends Zip { | |||||
protected void zipFile(File file, ZipOutputStream zOut, String vPath) | protected void zipFile(File file, ZipOutputStream zOut, String vPath) | ||||
throws IOException | throws IOException | ||||
{ | { | ||||
// If the file being added is META-INF/MANIFEST.MF, we merge it with the | |||||
// current manifest | |||||
// If the file being added is META-INF/MANIFEST.MF, we warn if it's not the | |||||
// one specified in the "manifest" attribute - or if it's being added twice, | |||||
// meaning the same file is specified by the "manifeset" attribute and in | |||||
// a <fileset> element. | |||||
if (vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) { | if (vPath.equalsIgnoreCase("META-INF/MANIFEST.MF")) { | ||||
InputStream is = null; | |||||
try { | |||||
is = new FileInputStream(file); | |||||
zipManifestEntry(is); | |||||
} | |||||
catch (IOException e) { | |||||
throw new BuildException("Unable to read manifest file: " + file, e); | |||||
} | |||||
finally { | |||||
if (is != null) { | |||||
try { | |||||
is.close(); | |||||
} | |||||
catch (IOException e) { | |||||
// do nothing | |||||
} | |||||
} | |||||
} | |||||
log("Warning: selected "+archiveType+" files include a META-INF/MANIFEST.MF which will be ignored " + | |||||
"(please use manifest attribute to "+archiveType+" task)", Project.MSG_WARN); | |||||
} else { | } else { | ||||
super.zipFile(file, zOut, vPath); | super.zipFile(file, zOut, vPath); | ||||
} | } | ||||
} | } | ||||
protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, long lastModified) | protected void zipFile(InputStream is, ZipOutputStream zOut, String vPath, long lastModified) | ||||
@@ -82,6 +82,7 @@ import java.io.File; | |||||
* <li>failonerror | * <li>failonerror | ||||
* <li>includeantruntime | * <li>includeantruntime | ||||
* <li>includejavaruntime | * <li>includejavaruntime | ||||
* <li>source | |||||
* </ul> | * </ul> | ||||
* Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required. | * Of these arguments, the <b>sourcedir</b> and <b>destdir</b> are required. | ||||
* <p> | * <p> | ||||
@@ -122,6 +123,24 @@ public class Javac extends MatchingTask { | |||||
protected boolean failOnError = true; | protected boolean failOnError = true; | ||||
protected File[] compileList = new File[0]; | protected File[] compileList = new File[0]; | ||||
private String source; | |||||
/** | |||||
* Get the value of source. | |||||
* @return value of source. | |||||
*/ | |||||
public String getSource() { | |||||
return source; | |||||
} | |||||
/** | |||||
* Set the value of source. | |||||
* @param v Value to assign to source. | |||||
*/ | |||||
public void setSource(String v) { | |||||
this.source = v; | |||||
} | |||||
/** | /** | ||||
* Create a nested <src ...> element for multiple source path | * Create a nested <src ...> element for multiple source path | ||||
* support. | * support. | ||||
@@ -433,7 +452,15 @@ public class Javac extends MatchingTask { | |||||
*/ | */ | ||||
public void setFork(boolean fork) | public void setFork(boolean fork) | ||||
{ | { | ||||
this.fork = fork; | |||||
this.fork = fork; | |||||
} | |||||
/** | |||||
* Is this a forked invocation of JDK's javac? | |||||
*/ | |||||
public boolean isForkedJavac() { | |||||
return fork || | |||||
"extJavac".equals(project.getProperty("build.compiler")); | |||||
} | } | ||||
@@ -489,8 +516,8 @@ public class Javac extends MatchingTask { | |||||
String compiler = project.getProperty("build.compiler"); | String compiler = project.getProperty("build.compiler"); | ||||
if (fork) { | |||||
if (compiler != null) { | |||||
if (fork) { | |||||
if (compiler != null) { | |||||
if (isJdkCompiler(compiler)) { | if (isJdkCompiler(compiler)) { | ||||
log("Since fork is true, ignoring build.compiler setting.", | log("Since fork is true, ignoring build.compiler setting.", | ||||
Project.MSG_WARN); | Project.MSG_WARN); | ||||
@@ -499,13 +526,13 @@ public class Javac extends MatchingTask { | |||||
else { | else { | ||||
log("Since build.compiler setting isn't classic or modern, ignoring fork setting.", Project.MSG_WARN); | log("Since build.compiler setting isn't classic or modern, ignoring fork setting.", Project.MSG_WARN); | ||||
} | } | ||||
} | |||||
} | |||||
else { | else { | ||||
compiler = "extJavac"; | compiler = "extJavac"; | ||||
} | } | ||||
} | |||||
} | |||||
if (compiler == null) { | |||||
if (compiler == null) { | |||||
if (Project.getJavaVersion() != Project.JAVA_1_1 && | if (Project.getJavaVersion() != Project.JAVA_1_1 && | ||||
Project.getJavaVersion() != Project.JAVA_1_2) { | Project.getJavaVersion() != Project.JAVA_1_2) { | ||||
compiler = "modern"; | compiler = "modern"; | ||||
@@ -512,8 +512,13 @@ public class SQLExec extends Task { | |||||
project.getProperties()); | project.getProperties()); | ||||
if (line.startsWith("//")) continue; | if (line.startsWith("//")) continue; | ||||
if (line.startsWith("--")) continue; | if (line.startsWith("--")) continue; | ||||
if (line.length() > 2 && | |||||
line.substring(0,3).equalsIgnoreCase("REM")) continue; | |||||
StringTokenizer st = new StringTokenizer(line); | |||||
if (st.hasMoreTokens()) { | |||||
String token = st.nextToken(); | |||||
if ("REM".equalsIgnoreCase(token)) { | |||||
continue; | |||||
} | |||||
} | |||||
sql += " " + line; | sql += " " + line; | ||||
sql = sql.trim(); | sql = sql.trim(); | ||||
@@ -216,11 +216,21 @@ public abstract class DefaultCompilerAdapter implements CompilerAdapter { | |||||
boolean usingJava1_1 = Project.getJavaVersion().equals(Project.JAVA_1_1); | boolean usingJava1_1 = Project.getJavaVersion().equals(Project.JAVA_1_1); | ||||
String memoryParameterPrefix = usingJava1_1 ? "-J-" : "-J-X"; | String memoryParameterPrefix = usingJava1_1 ? "-J-" : "-J-X"; | ||||
if (memoryInitialSize != null) { | if (memoryInitialSize != null) { | ||||
cmd.createArgument().setValue(memoryParameterPrefix+"ms"+memoryInitialSize); | |||||
if (!attributes.isForkedJavac()) { | |||||
attributes.log("Since fork is false, ignoring memoryInitialSize setting.", | |||||
Project.MSG_WARN); | |||||
} else { | |||||
cmd.createArgument().setValue(memoryParameterPrefix+"ms"+memoryInitialSize); | |||||
} | |||||
} | } | ||||
if (memoryMaximumSize != null) { | if (memoryMaximumSize != null) { | ||||
cmd.createArgument().setValue(memoryParameterPrefix+"mx"+memoryMaximumSize); | |||||
if (!attributes.isForkedJavac()) { | |||||
attributes.log("Since fork is false, ignoring memoryMaximumSize setting.", | |||||
Project.MSG_WARN); | |||||
} else { | |||||
cmd.createArgument().setValue(memoryParameterPrefix+"mx"+memoryMaximumSize); | |||||
} | |||||
} | } | ||||
if (attributes.getNowarn()) { | if (attributes.getNowarn()) { | ||||
@@ -303,6 +313,23 @@ public abstract class DefaultCompilerAdapter implements CompilerAdapter { | |||||
return cmd; | return cmd; | ||||
} | } | ||||
/** | |||||
* Does the command line argument processing common to classic and | |||||
* modern and adds the files to compile as well. | |||||
*/ | |||||
protected Commandline setupModernJavacCommand() { | |||||
Commandline cmd = new Commandline(); | |||||
setupJavacCommandlineSwitches(cmd); | |||||
if (attributes.getSource() != null) { | |||||
cmd.createArgument().setValue("-source"); | |||||
cmd.createArgument().setValue(attributes.getSource()); | |||||
} | |||||
logAndAddFilesToCompile(cmd); | |||||
return cmd; | |||||
} | |||||
/** | /** | ||||
* Does the command line argument processing common to classic and | * Does the command line argument processing common to classic and | ||||
* modern and adds the files to compile as well. | * modern and adds the files to compile as well. | ||||
@@ -81,7 +81,7 @@ public class Javac13 extends DefaultCompilerAdapter { | |||||
public boolean execute() throws BuildException { | public boolean execute() throws BuildException { | ||||
attributes.log("Using modern compiler", Project.MSG_VERBOSE); | attributes.log("Using modern compiler", Project.MSG_VERBOSE); | ||||
Commandline cmd = setupJavacCommand(); | |||||
Commandline cmd = setupModernJavacCommand(); | |||||
// Use reflection to be able to build on all JDKs >= 1.1: | // Use reflection to be able to build on all JDKs >= 1.1: | ||||
try { | try { | ||||
@@ -200,7 +200,7 @@ public class Cab extends MatchingTask { | |||||
if (cmdOptions != null) | if (cmdOptions != null) | ||||
{ | { | ||||
command.createArgument().setValue(cmdOptions); | |||||
command.createArgument().setLine(cmdOptions); | |||||
} | } | ||||
command.createArgument().setValue("n"); | command.createArgument().setValue("n"); | ||||
@@ -257,7 +257,7 @@ public class Depend extends MatchingTask { | |||||
classFileInfoMap = new Hashtable(); | classFileInfoMap = new Hashtable(); | ||||
boolean cacheDirty = false; | boolean cacheDirty = false; | ||||
Hashtable dependencyMap = null; | |||||
Hashtable dependencyMap = new Hashtable(); | |||||
File depCacheFile = null; | File depCacheFile = null; | ||||
boolean depCacheFileExists = true; | boolean depCacheFileExists = true; | ||||
long depCacheFileLastModified = Long.MAX_VALUE; | long depCacheFileLastModified = Long.MAX_VALUE; | ||||
@@ -806,12 +806,12 @@ public class FTP | |||||
} | } | ||||
if( ! ftp.makeDirectory( dir ) ) { | if( ! ftp.makeDirectory( dir ) ) { | ||||
// Both codes 550 and 553 can be produced by FTP Servers | |||||
// codes 521, 550 and 553 can be produced by FTP Servers | |||||
// to indicate that an attempt to create a directory has | // to indicate that an attempt to create a directory has | ||||
// failed because the directory already exists. | // failed because the directory already exists. | ||||
int rc = ftp.getReplyCode(); | int rc = ftp.getReplyCode(); | ||||
if( rc != 550 && rc != 553 && !ignoreNoncriticalErrors) { | |||||
if( !(ignoreNoncriticalErrors && (rc == 550 || rc == 553 || rc==521))) { | |||||
throw new BuildException( "could not create directory: " + | throw new BuildException( "could not create directory: " + | ||||
ftp.getReplyString() ); | ftp.getReplyString() ); | ||||
} | } | ||||
@@ -84,303 +84,303 @@ import java.io.*; | |||||
* @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | * @author <a href="sbailliez@imediation.com">Stephane Bailliez</a> | ||||
*/ | */ | ||||
public class CovReport extends Task { | public class CovReport extends Task { | ||||
/* | |||||
jpcoverport [options] -output=file -snapshot=snapshot.jpc | |||||
jpcovreport [options] [-paramfile=file] -output=<fileName> -snapshot=<fileName> | |||||
Generate a report based on the indicated snapshot | |||||
/* | |||||
jpcoverport [options] -output=file -snapshot=snapshot.jpc | |||||
jpcovreport [options] [-paramfile=file] -output=<fileName> -snapshot=<fileName> | |||||
-paramfile=file | |||||
A text file containing the report generation options. | |||||
Generate a report based on the indicated snapshot | |||||
-format=(html|text|xml) defaults to html | |||||
The format of the generated report. | |||||
-paramfile=file | |||||
A text file containing the report generation options. | |||||
-type=(executive|summary|detailed|verydetailed) defaults to detailed | |||||
The type of report to be generated. For -format=xml, | |||||
use -type=verydetailed to include source code lines. | |||||
-format=(html|text|xml) defaults to html | |||||
The format of the generated report. | |||||
Note: A very detailed report can be VERY large. | |||||
-type=(executive|summary|detailed|verydetailed) defaults to detailed | |||||
The type of report to be generated. For -format=xml, | |||||
use -type=verydetailed to include source code lines. | |||||
-percent=num Min 1 Max 101 Default 101 | |||||
An integer representing a percentage of coverage. | |||||
Only methods with test case coverage less than the | |||||
percentage are included in reports. | |||||
Note: A very detailed report can be VERY large. | |||||
-filters=string | |||||
A comma-separated list of filters in the form | |||||
<package>.<class>:V, where V can be I for Include or | |||||
E for Exclude. For the default package, omit <package>. | |||||
-percent=num Min 1 Max 101 Default 101 | |||||
An integer representing a percentage of coverage. | |||||
Only methods with test case coverage less than the | |||||
percentage are included in reports. | |||||
-filters_method=string | |||||
Optional. A comma-separated list of methods that | |||||
correspond one-to-one with the entries in -filters. | |||||
-filters=string | |||||
A comma-separated list of filters in the form | |||||
<package>.<class>:V, where V can be I for Include or | |||||
E for Exclude. For the default package, omit <package>. | |||||
-output=string Must be specified | |||||
The absolute path and file name for the generated | |||||
report file. | |||||
-filters_method=string | |||||
Optional. A comma-separated list of methods that | |||||
correspond one-to-one with the entries in -filters. | |||||
-snapshot=string Must be specified | |||||
The absolute path and file name of the snapshot file. | |||||
-output=string Must be specified | |||||
The absolute path and file name for the generated | |||||
report file. | |||||
-inc_src_text=(on|off) defaults to on | |||||
Include text of the source code lines. | |||||
Only applies for -format=xml and -type=verydetailed. | |||||
-snapshot=string Must be specified | |||||
The absolute path and file name of the snapshot file. | |||||
-sourcepath=string defaults to . | |||||
A semicolon-separated list of source paths. | |||||
/* | |||||
-inc_src_text=(on|off) defaults to on | |||||
Include text of the source code lines. | |||||
Only applies for -format=xml and -type=verydetailed. | |||||
/** coverage home, mandatory */ | |||||
private File home = null; | |||||
/** format of generated report, optional */ | |||||
private String format = null; | |||||
/** the name of the output snapshot, mandatory */ | |||||
private File tofile = null; | |||||
/** type of report, optional */ | |||||
private String type = null; | |||||
/** threshold value for printing methods, optional */ | |||||
private Integer percent = null; | |||||
/** comma separated list of filters (???)*/ | |||||
private String filters = null; | |||||
/** name of the snapshot file to create report from */ | |||||
private File snapshot = null; | |||||
/** sourcepath to use */ | |||||
private Path sourcePath = null; | |||||
/** include the text for each line of code (xml report verydetailed)*/ | |||||
private boolean includeSource = true; | |||||
private Path coveragePath = null; | |||||
/** */ | |||||
private Reference reference = null; | |||||
/** | |||||
* Set the coverage home. it must point to JProbe coverage | |||||
* directories where are stored native libraries and jars. | |||||
*/ | |||||
public void setHome(File value) { | |||||
this.home = value; | |||||
} | |||||
public static class ReportFormat extends EnumeratedAttribute { | |||||
public String[] getValues(){ | |||||
return new String[]{"html", "text", "xml"}; | |||||
} | |||||
} | |||||
/** set the format of the report html|text|xml*/ | |||||
public void setFormat(ReportFormat value){ | |||||
this.format = value.getValue(); | |||||
} | |||||
public static class ReportType extends EnumeratedAttribute { | |||||
public String[] getValues(){ | |||||
return new String[]{"executive", "summary", "detailed", "verydetailed"}; | |||||
} | |||||
} | |||||
/** sets the report type executive|summary|detailed|verydetailed */ | |||||
public void setType(ReportType value){ | |||||
this.type = value.getValue(); | |||||
} | |||||
/** include source code lines. XML report only */ | |||||
public void setIncludesource(boolean value){ | |||||
this.includeSource = value; | |||||
} | |||||
/** sets the threshold printing method 0-100*/ | |||||
public void setPercent(Integer value){ | |||||
this.percent = value; | |||||
} | |||||
/** set the filters */ | |||||
public void setFilters(String values){ | |||||
this.filters = values; | |||||
} | |||||
public Path createSourcepath(){ | |||||
if (sourcePath == null) { | |||||
sourcePath = new Path(project); | |||||
} | |||||
return sourcePath.createPath(); | |||||
} | |||||
public void setSnapshot(File value){ | |||||
this.snapshot = value; | |||||
} | |||||
/** | |||||
* Set the output snapshot file | |||||
*/ | |||||
public void setTofile(File value) { | |||||
this.tofile = value; | |||||
} | |||||
//@todo to remove | |||||
public Path createCoveragepath(){ | |||||
if (coveragePath == null) { | |||||
coveragePath = new Path(project); | |||||
} | |||||
return coveragePath.createPath(); | |||||
} | |||||
public Reference createReference(){ | |||||
if (reference == null){ | |||||
reference = new Reference(); | |||||
} | |||||
return reference; | |||||
} | |||||
public CovReport() { | |||||
} | |||||
/** check for mandatory options */ | |||||
protected void checkOptions() throws BuildException { | |||||
if (tofile == null) { | |||||
throw new BuildException("'tofile' attribute must be set."); | |||||
} | |||||
if (snapshot == null) { | |||||
throw new BuildException("'snapshot' attribute must be set."); | |||||
} | |||||
if (home == null) { | |||||
throw new BuildException("'home' attribute must be set to JProbe home directory"); | |||||
} | |||||
home = new File(home,"Coverage"); | |||||
File jar = new File(home, "coverage.jar"); | |||||
if (!jar.exists()) { | |||||
throw new BuildException("Cannot find Coverage directory: " + home); | |||||
} | |||||
if (reference != null && !"xml".equals(format)){ | |||||
log("Ignored reference. It cannot be used in non XML report."); | |||||
reference = null; // nullify it so that there is no ambiguity | |||||
} | |||||
} | |||||
public void execute() throws BuildException { | |||||
checkOptions(); | |||||
try { | |||||
Commandline cmdl = new Commandline(); | |||||
// we need to run Coverage from his directory due to dll/jar issues | |||||
cmdl.setExecutable( new File(home, "jpcovreport").getAbsolutePath() ); | |||||
String[] params = getParameters(); | |||||
for (int i = 0; i < params.length; i++) { | |||||
cmdl.createArgument().setValue(params[i]); | |||||
} | |||||
// use the custom handler for stdin issues | |||||
LogStreamHandler handler = new LogStreamHandler(this,Project.MSG_INFO,Project.MSG_WARN); | |||||
Execute exec = new Execute( handler ); | |||||
log(cmdl.toString(), Project.MSG_VERBOSE); | |||||
exec.setCommandline(cmdl.getCommandline()); | |||||
int exitValue = exec.execute(); | |||||
if (exitValue != 0) { | |||||
throw new BuildException("JProbe Coverage Report failed (" + exitValue + ")"); | |||||
} | |||||
log("coveragePath: " + coveragePath, Project.MSG_VERBOSE); | |||||
log("format: " + format, Project.MSG_VERBOSE); | |||||
if (reference != null && "xml".equals(format)){ | |||||
reference.createEnhancedXMLReport(); | |||||
} | |||||
} catch (IOException e){ | |||||
throw new BuildException("Failed to execute JProbe Coverage Report.", e); | |||||
} | |||||
} | |||||
protected String[] getParameters(){ | |||||
Vector v = new Vector(); | |||||
if (format != null) { | |||||
v.addElement("-format=" + format); | |||||
} | |||||
if (type != null) { | |||||
v.addElement("-type=" + type); | |||||
} | |||||
if (percent != null) { | |||||
v.addElement("-percent=" + percent); | |||||
} | |||||
if (filters != null) { | |||||
v.addElement("-filters=" + filters); | |||||
} | |||||
v.addElement("-output=" + project.resolveFile(tofile.getPath())); | |||||
v.addElement("-snapshot=" + project.resolveFile(snapshot.getPath())); | |||||
// as a default -sourcepath use . in JProbe, so use project . | |||||
if (sourcePath == null) { | |||||
sourcePath = new Path(project); | |||||
sourcePath.createPath().setLocation(project.resolveFile(".")); | |||||
} | |||||
v.addElement("-sourcepath=" + sourcePath); | |||||
if ("verydetailed".equalsIgnoreCase(format) && "xml".equalsIgnoreCase(type)) { | |||||
v.addElement("-inc_src_text=" + (includeSource ? "on" : "off")); | |||||
} | |||||
String[] params = new String[v.size()]; | |||||
v.copyInto(params); | |||||
return params; | |||||
} | |||||
public class Reference { | |||||
protected Path classPath; | |||||
protected ReportFilters filters; | |||||
public Path createClasspath(){ | |||||
if (classPath == null) { | |||||
classPath = new Path(project); | |||||
} | |||||
return classPath.createPath(); | |||||
} | |||||
public ReportFilters createFilters(){ | |||||
if (filters == null){ | |||||
filters = new ReportFilters(); | |||||
} | |||||
return filters; | |||||
} | |||||
protected void createEnhancedXMLReport() throws BuildException { | |||||
// we need a classpath element | |||||
if (classPath == null){ | |||||
throw new BuildException("Need a 'classpath' element."); | |||||
} | |||||
// and a valid one... | |||||
String[] paths = classPath.list(); | |||||
if (paths.length == 0){ | |||||
throw new BuildException("Coverage path is invalid. It does not contain any existing path."); | |||||
} | |||||
// and we need at least one filter include/exclude. | |||||
if (filters == null || filters.size() == 0){ | |||||
createFilters(); | |||||
log("Adding default include filter to *.*()", Project.MSG_VERBOSE); | |||||
ReportFilters.Include include = new ReportFilters.Include(); | |||||
filters.addInclude( include ); | |||||
} | |||||
try { | |||||
log("Creating enhanced XML report", Project.MSG_VERBOSE); | |||||
XMLReport report = new XMLReport(CovReport.this, tofile); | |||||
report.setReportFilters(filters); | |||||
report.setJProbehome( new File(home.getParent()) ); | |||||
Document doc = report.createDocument(paths); | |||||
TransformerFactory tfactory = TransformerFactory.newInstance(); | |||||
Transformer transformer = tfactory.newTransformer(); | |||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); | |||||
Source src = new DOMSource(doc); | |||||
Result res = new StreamResult( "file:///" + tofile.toString() ); | |||||
transformer.transform(src, res); | |||||
} catch (Exception e){ | |||||
throw new BuildException("Error while performing enhanced XML report from file " + tofile, e); | |||||
} | |||||
} | |||||
} | |||||
-sourcepath=string defaults to . | |||||
A semicolon-separated list of source paths. | |||||
/* | |||||
/** coverage home, mandatory */ | |||||
private File home = null; | |||||
/** format of generated report, optional */ | |||||
private String format = null; | |||||
/** the name of the output snapshot, mandatory */ | |||||
private File tofile = null; | |||||
/** type of report, optional */ | |||||
private String type = null; | |||||
/** threshold value for printing methods, optional */ | |||||
private Integer percent = null; | |||||
/** comma separated list of filters (???)*/ | |||||
private String filters = null; | |||||
/** name of the snapshot file to create report from */ | |||||
private File snapshot = null; | |||||
/** sourcepath to use */ | |||||
private Path sourcePath = null; | |||||
/** include the text for each line of code (xml report verydetailed)*/ | |||||
private boolean includeSource = true; | |||||
private Path coveragePath = null; | |||||
/** */ | |||||
private Reference reference = null; | |||||
/** | |||||
* Set the coverage home. it must point to JProbe coverage | |||||
* directories where are stored native libraries and jars. | |||||
*/ | |||||
public void setHome(File value) { | |||||
this.home = value; | |||||
} | |||||
public static class ReportFormat extends EnumeratedAttribute { | |||||
public String[] getValues(){ | |||||
return new String[]{"html", "text", "xml"}; | |||||
} | |||||
} | |||||
/** set the format of the report html|text|xml*/ | |||||
public void setFormat(ReportFormat value){ | |||||
this.format = value.getValue(); | |||||
} | |||||
public static class ReportType extends EnumeratedAttribute { | |||||
public String[] getValues(){ | |||||
return new String[]{"executive", "summary", "detailed", "verydetailed"}; | |||||
} | |||||
} | |||||
/** sets the report type executive|summary|detailed|verydetailed */ | |||||
public void setType(ReportType value){ | |||||
this.type = value.getValue(); | |||||
} | |||||
/** include source code lines. XML report only */ | |||||
public void setIncludesource(boolean value){ | |||||
this.includeSource = value; | |||||
} | |||||
/** sets the threshold printing method 0-100*/ | |||||
public void setPercent(Integer value){ | |||||
this.percent = value; | |||||
} | |||||
/** set the filters */ | |||||
public void setFilters(String values){ | |||||
this.filters = values; | |||||
} | |||||
public Path createSourcepath(){ | |||||
if (sourcePath == null) { | |||||
sourcePath = new Path(project); | |||||
} | |||||
return sourcePath.createPath(); | |||||
} | |||||
public void setSnapshot(File value){ | |||||
this.snapshot = value; | |||||
} | |||||
/** | |||||
* Set the output snapshot file | |||||
*/ | |||||
public void setTofile(File value) { | |||||
this.tofile = value; | |||||
} | |||||
//@todo to remove | |||||
public Path createCoveragepath(){ | |||||
if (coveragePath == null) { | |||||
coveragePath = new Path(project); | |||||
} | |||||
return coveragePath.createPath(); | |||||
} | |||||
public Reference createReference(){ | |||||
if (reference == null){ | |||||
reference = new Reference(); | |||||
} | |||||
return reference; | |||||
} | |||||
public CovReport() { | |||||
} | |||||
/** check for mandatory options */ | |||||
protected void checkOptions() throws BuildException { | |||||
if (tofile == null) { | |||||
throw new BuildException("'tofile' attribute must be set."); | |||||
} | |||||
if (snapshot == null) { | |||||
throw new BuildException("'snapshot' attribute must be set."); | |||||
} | |||||
if (home == null) { | |||||
throw new BuildException("'home' attribute must be set to JProbe home directory"); | |||||
} | |||||
home = new File(home,"Coverage"); | |||||
File jar = new File(home, "coverage.jar"); | |||||
if (!jar.exists()) { | |||||
throw new BuildException("Cannot find Coverage directory: " + home); | |||||
} | |||||
if (reference != null && !"xml".equals(format)){ | |||||
log("Ignored reference. It cannot be used in non XML report."); | |||||
reference = null; // nullify it so that there is no ambiguity | |||||
} | |||||
} | |||||
public void execute() throws BuildException { | |||||
checkOptions(); | |||||
try { | |||||
Commandline cmdl = new Commandline(); | |||||
// we need to run Coverage from his directory due to dll/jar issues | |||||
cmdl.setExecutable( new File(home, "jpcovreport").getAbsolutePath() ); | |||||
String[] params = getParameters(); | |||||
for (int i = 0; i < params.length; i++) { | |||||
cmdl.createArgument().setValue(params[i]); | |||||
} | |||||
// use the custom handler for stdin issues | |||||
LogStreamHandler handler = new LogStreamHandler(this,Project.MSG_INFO,Project.MSG_WARN); | |||||
Execute exec = new Execute( handler ); | |||||
log(cmdl.toString(), Project.MSG_VERBOSE); | |||||
exec.setCommandline(cmdl.getCommandline()); | |||||
int exitValue = exec.execute(); | |||||
if (exitValue != 0) { | |||||
throw new BuildException("JProbe Coverage Report failed (" + exitValue + ")"); | |||||
} | |||||
log("coveragePath: " + coveragePath, Project.MSG_VERBOSE); | |||||
log("format: " + format, Project.MSG_VERBOSE); | |||||
if (reference != null && "xml".equals(format)){ | |||||
reference.createEnhancedXMLReport(); | |||||
} | |||||
} catch (IOException e){ | |||||
throw new BuildException("Failed to execute JProbe Coverage Report.", e); | |||||
} | |||||
} | |||||
protected String[] getParameters(){ | |||||
Vector v = new Vector(); | |||||
if (format != null) { | |||||
v.addElement("-format=" + format); | |||||
} | |||||
if (type != null) { | |||||
v.addElement("-type=" + type); | |||||
} | |||||
if (percent != null) { | |||||
v.addElement("-percent=" + percent); | |||||
} | |||||
if (filters != null) { | |||||
v.addElement("-filters=" + filters); | |||||
} | |||||
v.addElement("-output=" + project.resolveFile(tofile.getPath())); | |||||
v.addElement("-snapshot=" + project.resolveFile(snapshot.getPath())); | |||||
// as a default -sourcepath use . in JProbe, so use project . | |||||
if (sourcePath == null) { | |||||
sourcePath = new Path(project); | |||||
sourcePath.createPath().setLocation(project.resolveFile(".")); | |||||
} | |||||
v.addElement("-sourcepath=" + sourcePath); | |||||
if ("verydetailed".equalsIgnoreCase(format) && "xml".equalsIgnoreCase(type)) { | |||||
v.addElement("-inc_src_text=" + (includeSource ? "on" : "off")); | |||||
} | |||||
String[] params = new String[v.size()]; | |||||
v.copyInto(params); | |||||
return params; | |||||
} | |||||
public class Reference { | |||||
protected Path classPath; | |||||
protected ReportFilters filters; | |||||
public Path createClasspath(){ | |||||
if (classPath == null) { | |||||
classPath = new Path(CovReport.this.project); | |||||
} | |||||
return classPath.createPath(); | |||||
} | |||||
public ReportFilters createFilters(){ | |||||
if (filters == null){ | |||||
filters = new ReportFilters(); | |||||
} | |||||
return filters; | |||||
} | |||||
protected void createEnhancedXMLReport() throws BuildException { | |||||
// we need a classpath element | |||||
if (classPath == null){ | |||||
throw new BuildException("Need a 'classpath' element."); | |||||
} | |||||
// and a valid one... | |||||
String[] paths = classPath.list(); | |||||
if (paths.length == 0){ | |||||
throw new BuildException("Coverage path is invalid. It does not contain any existing path."); | |||||
} | |||||
// and we need at least one filter include/exclude. | |||||
if (filters == null || filters.size() == 0){ | |||||
createFilters(); | |||||
log("Adding default include filter to *.*()", Project.MSG_VERBOSE); | |||||
ReportFilters.Include include = new ReportFilters.Include(); | |||||
filters.addInclude( include ); | |||||
} | |||||
try { | |||||
log("Creating enhanced XML report", Project.MSG_VERBOSE); | |||||
XMLReport report = new XMLReport(CovReport.this, tofile); | |||||
report.setReportFilters(filters); | |||||
report.setJProbehome( new File(home.getParent()) ); | |||||
Document doc = report.createDocument(paths); | |||||
TransformerFactory tfactory = TransformerFactory.newInstance(); | |||||
Transformer transformer = tfactory.newTransformer(); | |||||
transformer.setOutputProperty(OutputKeys.INDENT, "yes"); | |||||
transformer.setOutputProperty(OutputKeys.METHOD, "xml"); | |||||
Source src = new DOMSource(doc); | |||||
Result res = new StreamResult( "file:///" + tofile.toString() ); | |||||
transformer.transform(src, res); | |||||
} catch (Exception e){ | |||||
throw new BuildException("Error while performing enhanced XML report from file " + tofile, e); | |||||
} | |||||
} | |||||
} | |||||
} | } |
@@ -72,6 +72,7 @@ import java.util.Vector; | |||||
* @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a> | * @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a> | ||||
* @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a> | * @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</a> | ||||
* @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a> | ||||
* @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a> | |||||
*/ | */ | ||||
public class FileSet extends DataType { | public class FileSet extends DataType { | ||||
@@ -80,6 +81,7 @@ public class FileSet extends DataType { | |||||
private File dir; | private File dir; | ||||
private boolean useDefaultExcludes = true; | private boolean useDefaultExcludes = true; | ||||
private boolean isCaseSensitive = true; | |||||
public FileSet() { | public FileSet() { | ||||
super(); | super(); | ||||
@@ -90,6 +92,7 @@ public class FileSet extends DataType { | |||||
this.defaultPatterns = fileset.defaultPatterns; | this.defaultPatterns = fileset.defaultPatterns; | ||||
this.additionalPatterns = fileset.additionalPatterns; | this.additionalPatterns = fileset.additionalPatterns; | ||||
this.useDefaultExcludes = fileset.useDefaultExcludes; | this.useDefaultExcludes = fileset.useDefaultExcludes; | ||||
this.isCaseSensitive = fileset.isCaseSensitive; | |||||
} | } | ||||
@@ -244,6 +247,16 @@ public class FileSet extends DataType { | |||||
this.useDefaultExcludes = useDefaultExcludes; | this.useDefaultExcludes = useDefaultExcludes; | ||||
} | } | ||||
/** | |||||
* Sets case sensitivity of the file system | |||||
* | |||||
* @param isCaseSensitive "true"|"on"|"yes" if file system is case | |||||
* sensitive, "false"|"off"|"no" when not. | |||||
*/ | |||||
public void setCaseSensitive(boolean isCaseSensitive) { | |||||
this.isCaseSensitive = isCaseSensitive; | |||||
} | |||||
/** | /** | ||||
* Returns the directory scanner needed to access the files to process. | * Returns the directory scanner needed to access the files to process. | ||||
*/ | */ | ||||
@@ -287,6 +300,7 @@ public class FileSet extends DataType { | |||||
ds.setIncludes(defaultPatterns.getIncludePatterns(p)); | ds.setIncludes(defaultPatterns.getIncludePatterns(p)); | ||||
ds.setExcludes(defaultPatterns.getExcludePatterns(p)); | ds.setExcludes(defaultPatterns.getExcludePatterns(p)); | ||||
if (useDefaultExcludes) ds.addDefaultExcludes(); | if (useDefaultExcludes) ds.addDefaultExcludes(); | ||||
ds.setCaseSensitive(isCaseSensitive); | |||||
} | } | ||||
/** | /** | ||||
@@ -72,7 +72,7 @@ import org.apache.tools.ant.Task; | |||||
/** | /** | ||||
* A set of filters to be applied to something. | * A set of filters to be applied to something. | ||||
* | * | ||||
* A filter set may have starttoken and endtokens defined. | |||||
* A filter set may have begintoken and endtokens defined. | |||||
* | * | ||||
* @author <A href="mailto:gholam@xtra.co.nz"> Michael McCallum </A> | * @author <A href="mailto:gholam@xtra.co.nz"> Michael McCallum </A> | ||||
* @created 14 March 2001 | * @created 14 March 2001 | ||||
@@ -324,7 +324,7 @@ public class FilterSet extends DataType { | |||||
/** | /** | ||||
* Does replacement on the given string with token matching. | * Does replacement on the given string with token matching. | ||||
* This uses the defined starttoken and endtoken values which default to @ for both. | |||||
* This uses the defined begintoken and endtoken values which default to @ for both. | |||||
* | * | ||||
* @param line The line to process the tokens in. | * @param line The line to process the tokens in. | ||||
* @return The string with the tokens replaced. | * @return The string with the tokens replaced. | ||||
@@ -93,7 +93,7 @@ public class FilterSetCollection { | |||||
/** | /** | ||||
* Does replacement on the given string with token matching. | * Does replacement on the given string with token matching. | ||||
* This uses the defined starttoken and endtoken values which default to @ for both. | |||||
* This uses the defined begintoken and endtoken values which default to @ for both. | |||||
* | * | ||||
* @param line The line to process the tokens in. | * @param line The line to process the tokens in. | ||||
* @return The string with the tokens replaced. | * @return The string with the tokens replaced. | ||||
@@ -74,11 +74,14 @@ public class SourceFileScanner { | |||||
protected Task task; | protected Task task; | ||||
private FileUtils fileUtils; | |||||
/** | /** | ||||
* @param task The task we should log messages through | * @param task The task we should log messages through | ||||
*/ | */ | ||||
public SourceFileScanner(Task task) { | public SourceFileScanner(Task task) { | ||||
this.task = task; | this.task = task; | ||||
fileUtils = FileUtils.newFileUtils(); | |||||
} | } | ||||
/** | /** | ||||
@@ -118,7 +121,7 @@ public class SourceFileScanner { | |||||
continue; | continue; | ||||
} | } | ||||
File src = new File(srcDir, files[i]); | |||||
File src = fileUtils.resolveFile(srcDir, files[i]); | |||||
if (src.lastModified() > now) { | if (src.lastModified() > now) { | ||||
task.log("Warning: "+files[i]+" modified in the future.", | task.log("Warning: "+files[i]+" modified in the future.", | ||||
Project.MSG_WARN); | Project.MSG_WARN); | ||||
@@ -131,7 +134,7 @@ public class SourceFileScanner { | |||||
if (destDir == null) { | if (destDir == null) { | ||||
dest = new File(targets[j]); | dest = new File(targets[j]); | ||||
} else { | } else { | ||||
dest = new File(destDir, targets[j]); | |||||
dest = fileUtils.resolveFile(destDir, targets[j]); | |||||
} | } | ||||
if (!dest.exists()) { | if (!dest.exists()) { | ||||