summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattinger <[email protected]>2006-07-06 21:53:00 +0000
committermattinger <[email protected]>2006-07-06 21:53:00 +0000
commit1159111b7a71b72eb04326df33211e1733f7e742 (patch)
treef0a80c384f633e521649654ab78e6239cf5e0d6f
Initial addition into subversion with build script changes
git-svn-id: file:///home/sven/projects/JOGL/temp/ant-contrib/svn/ant-contrib-code/trunk/ant-contrib@5 32d7a393-a5a9-423c-abd3-5d954feb1f2f
-rw-r--r--build.properties3
-rw-r--r--build.xml202
-rw-r--r--docs/LICENSE.txt47
-rw-r--r--docs/manual/index.html91
-rw-r--r--docs/manual/tasks/antcallback_task.html177
-rw-r--r--docs/manual/tasks/antclipse_task.html139
-rw-r--r--docs/manual/tasks/antfetch_task.html151
-rw-r--r--docs/manual/tasks/assert_task.html260
-rw-r--r--docs/manual/tasks/compilewithwalls.html135
-rw-r--r--docs/manual/tasks/for.html198
-rw-r--r--docs/manual/tasks/foreach.html145
-rw-r--r--docs/manual/tasks/forget.html62
-rw-r--r--docs/manual/tasks/if.html94
-rw-r--r--docs/manual/tasks/index.html16
-rw-r--r--docs/manual/tasks/inifile.html110
-rw-r--r--docs/manual/tasks/limit_task.html280
-rw-r--r--docs/manual/tasks/math_task.html405
-rw-r--r--docs/manual/tasks/more_conditions.html461
-rw-r--r--docs/manual/tasks/osfamily.html36
-rw-r--r--docs/manual/tasks/outofdate.html326
-rw-r--r--docs/manual/tasks/pathtofileset.html73
-rw-r--r--docs/manual/tasks/performance_monitor.html159
-rw-r--r--docs/manual/tasks/post_task.html366
-rw-r--r--docs/manual/tasks/propertycopy.html69
-rw-r--r--docs/manual/tasks/propertyregex.html133
-rw-r--r--docs/manual/tasks/propertyselector.html139
-rw-r--r--docs/manual/tasks/runtarget.html38
-rw-r--r--docs/manual/tasks/server_tasks.html260
-rw-r--r--docs/manual/tasks/shellscript.html140
-rw-r--r--docs/manual/tasks/sortlist.html145
-rw-r--r--docs/manual/tasks/stopwatch_task.html115
-rw-r--r--docs/manual/tasks/switch.html82
-rw-r--r--docs/manual/tasks/throw.html39
-rw-r--r--docs/manual/tasks/timestampselector.html132
-rw-r--r--docs/manual/tasks/toc.html64
-rw-r--r--docs/manual/tasks/trycatch.html96
-rw-r--r--docs/manual/tasks/urlencode.html78
-rw-r--r--docs/manual/tasks/variable_task.html261
-rw-r--r--docs/manual/tasks/verifydesign.html264
-rw-r--r--docs/manual/tasks/verifylegacytutorial.html71
-rw-r--r--docs/manual/tasks/verifynewprojtutorial.html39
-rw-r--r--ivy-conf.xml20
-rw-r--r--ivy.xml27
-rw-r--r--lib/ant/jars/ant-1.6.5.jarbin0 -> 1034049 bytes
-rw-r--r--lib/bcel/jars/bcel-5.1.jarbin0 -> 515920 bytes
-rw-r--r--lib/commons-cli/jars/commons-cli-1.0.jarbin0 -> 30117 bytes
-rw-r--r--lib/commons-codec/jars/commons-codec-1.3.jarbin0 -> 30085 bytes
-rw-r--r--lib/commons-httpclient/jars/commons-httpclient-3.0.1.jarbin0 -> 279383 bytes
-rw-r--r--lib/commons-logging/jars/commons-logging-1.0.4.jarbin0 -> 31605 bytes
-rw-r--r--lib/ivy/jars/ivy-1.3.1.jarbin0 -> 362782 bytes
-rw-r--r--lib/junit/jars/junit-3.8.1.jarbin0 -> 121070 bytes
-rw-r--r--lib/oro/jars/oro-2.0.8.jarbin0 -> 65261 bytes
-rw-r--r--lib/xercesImpl/jars/xercesImpl-2.6.2.jarbin0 -> 1010675 bytes
-rw-r--r--src/java/net/sf/antcontrib/AntContribVersion.java70
-rw-r--r--src/java/net/sf/antcontrib/antclipse/ClassPathParser.java105
-rw-r--r--src/java/net/sf/antcontrib/antclipse/ClassPathTask.java419
-rw-r--r--src/java/net/sf/antcontrib/antcontrib.properties55
-rw-r--r--src/java/net/sf/antcontrib/antlib.xml9
-rw-r--r--src/java/net/sf/antcontrib/antserver/Command.java82
-rw-r--r--src/java/net/sf/antcontrib/antserver/Response.java112
-rw-r--r--src/java/net/sf/antcontrib/antserver/Util.java67
-rw-r--r--src/java/net/sf/antcontrib/antserver/client/Client.java251
-rw-r--r--src/java/net/sf/antcontrib/antserver/client/ClientTask.java203
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java69
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java57
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java51
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java65
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java65
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java203
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java176
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java171
-rw-r--r--src/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java51
-rw-r--r--src/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java198
-rw-r--r--src/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java231
-rw-r--r--src/java/net/sf/antcontrib/antserver/server/Server.java126
-rw-r--r--src/java/net/sf/antcontrib/antserver/server/ServerTask.java68
-rw-r--r--src/java/net/sf/antcontrib/design/Depends.java51
-rw-r--r--src/java/net/sf/antcontrib/design/Design.java271
-rw-r--r--src/java/net/sf/antcontrib/design/DesignFileHandler.java336
-rw-r--r--src/java/net/sf/antcontrib/design/InstructionVisitor.java126
-rw-r--r--src/java/net/sf/antcontrib/design/Log.java28
-rw-r--r--src/java/net/sf/antcontrib/design/Package.java110
-rw-r--r--src/java/net/sf/antcontrib/design/VerifyDesign.java72
-rw-r--r--src/java/net/sf/antcontrib/design/VerifyDesignDelegate.java424
-rw-r--r--src/java/net/sf/antcontrib/design/VisitorImpl.java211
-rw-r--r--src/java/net/sf/antcontrib/inifile/IniFile.java232
-rw-r--r--src/java/net/sf/antcontrib/inifile/IniFileTask.java326
-rw-r--r--src/java/net/sf/antcontrib/inifile/IniPart.java39
-rw-r--r--src/java/net/sf/antcontrib/inifile/IniProperty.java106
-rw-r--r--src/java/net/sf/antcontrib/inifile/IniSection.java147
-rw-r--r--src/java/net/sf/antcontrib/input/GUIInputHandler.java78
-rw-r--r--src/java/net/sf/antcontrib/logic/AntCallBack.java644
-rw-r--r--src/java/net/sf/antcontrib/logic/AntFetch.java638
-rw-r--r--src/java/net/sf/antcontrib/logic/Assert.java81
-rw-r--r--src/java/net/sf/antcontrib/logic/ForEach.java423
-rw-r--r--src/java/net/sf/antcontrib/logic/ForTask.java433
-rw-r--r--src/java/net/sf/antcontrib/logic/IfTask.java221
-rw-r--r--src/java/net/sf/antcontrib/logic/OutOfDate.java675
-rw-r--r--src/java/net/sf/antcontrib/logic/RunTargetTask.java50
-rw-r--r--src/java/net/sf/antcontrib/logic/Switch.java207
-rw-r--r--src/java/net/sf/antcontrib/logic/Throw.java50
-rw-r--r--src/java/net/sf/antcontrib/logic/TimestampSelector.java285
-rw-r--r--src/java/net/sf/antcontrib/logic/TryCatchTask.java232
-rw-r--r--src/java/net/sf/antcontrib/math/Evaluateable.java28
-rw-r--r--src/java/net/sf/antcontrib/math/Math.java584
-rw-r--r--src/java/net/sf/antcontrib/math/MathTask.java137
-rw-r--r--src/java/net/sf/antcontrib/math/Numeric.java95
-rw-r--r--src/java/net/sf/antcontrib/math/Operation.java167
-rw-r--r--src/java/net/sf/antcontrib/net/PostTask.java751
-rw-r--r--src/java/net/sf/antcontrib/net/Prop.java41
-rw-r--r--src/java/net/sf/antcontrib/perf/AntPerformanceListener.java320
-rw-r--r--src/java/net/sf/antcontrib/perf/StopWatch.java193
-rw-r--r--src/java/net/sf/antcontrib/perf/StopWatchTask.java100
-rw-r--r--src/java/net/sf/antcontrib/platform/OsFamily.java72
-rw-r--r--src/java/net/sf/antcontrib/platform/Platform.java217
-rw-r--r--src/java/net/sf/antcontrib/platform/ShellScriptTask.java167
-rw-r--r--src/java/net/sf/antcontrib/process/ForgetTask.java62
-rw-r--r--src/java/net/sf/antcontrib/process/Limit.java402
-rw-r--r--src/java/net/sf/antcontrib/property/AbstractPropertySetterTask.java84
-rw-r--r--src/java/net/sf/antcontrib/property/PathFilterTask.java102
-rw-r--r--src/java/net/sf/antcontrib/property/PathToFileSet.java114
-rw-r--r--src/java/net/sf/antcontrib/property/PropertyCopy.java109
-rw-r--r--src/java/net/sf/antcontrib/property/PropertySelector.java142
-rw-r--r--src/java/net/sf/antcontrib/property/RegexTask.java199
-rw-r--r--src/java/net/sf/antcontrib/property/RegexUtil.java166
-rw-r--r--src/java/net/sf/antcontrib/property/SortList.java293
-rw-r--r--src/java/net/sf/antcontrib/property/URLEncodeTask.java94
-rw-r--r--src/java/net/sf/antcontrib/property/Variable.java352
-rw-r--r--src/java/net/sf/antcontrib/util/Reflector.java193
-rw-r--r--src/java/net/sf/antcontrib/util/ThreadPool.java63
-rw-r--r--src/java/net/sf/antcontrib/util/ThreadPoolThread.java67
-rw-r--r--src/java/net/sf/antcontrib/walls/CompileWithWalls.java369
-rw-r--r--src/java/net/sf/antcontrib/walls/Package.java175
-rw-r--r--src/java/net/sf/antcontrib/walls/SilentCopy.java45
-rw-r--r--src/java/net/sf/antcontrib/walls/SilentMove.java45
-rw-r--r--src/java/net/sf/antcontrib/walls/Walls.java78
-rw-r--r--src/java/net/sf/antcontrib/walls/WallsFileHandler.java116
-rw-r--r--test/resources/antclipse/.classpath9
-rw-r--r--test/resources/antclipse/antclipsetest.xml42
-rw-r--r--test/resources/antserver/antservertest.xml138
-rw-r--r--test/resources/antserver/clientfile.txt1
-rw-r--r--test/resources/design/designfiles/arraydepend.xml6
-rw-r--r--test/resources/design/designfiles/arraydepend2.xml6
-rw-r--r--test/resources/design/designfiles/arraydepend3.xml6
-rw-r--r--test/resources/design/designfiles/badxml.xml6
-rw-r--r--test/resources/design/designfiles/castdepend.xml6
-rw-r--r--test/resources/design/designfiles/catchdepend.xml6
-rw-r--r--test/resources/design/designfiles/declarejavautil.xml6
-rw-r--r--test/resources/design/designfiles/declarejavautilfail.xml8
-rw-r--r--test/resources/design/designfiles/declarejavax.xml6
-rw-r--r--test/resources/design/designfiles/declarejavaxpass.xml7
-rw-r--r--test/resources/design/designfiles/fielddepend.xml6
-rw-r--r--test/resources/design/designfiles/fieldrefdepend.xml6
-rw-r--r--test/resources/design/designfiles/innerclassdepend.xml6
-rw-r--r--test/resources/design/designfiles/instanceofdepend.xml6
-rw-r--r--test/resources/design/designfiles/interfacedepend.xml6
-rw-r--r--test/resources/design/designfiles/localvardepend.xml9
-rw-r--r--test/resources/design/designfiles/localvarrefdepend.xml6
-rw-r--r--test/resources/design/designfiles/missingattribute.xml6
-rw-r--r--test/resources/design/designfiles/multipleerrors.xml7
-rw-r--r--test/resources/design/designfiles/newdepend.xml6
-rw-r--r--test/resources/design/designfiles/newdepend2.xml6
-rw-r--r--test/resources/design/designfiles/nodebugoption.xml6
-rw-r--r--test/resources/design/designfiles/nojar.xml6
-rw-r--r--test/resources/design/designfiles/paramdepend.xml6
-rw-r--r--test/resources/design/designfiles/passlocaldepend.xml6
-rw-r--r--test/resources/design/designfiles/pathelementpath.xml7
-rw-r--r--test/resources/design/designfiles/putstatic.xml6
-rw-r--r--test/resources/design/designfiles/recursion.xml6
-rw-r--r--test/resources/design/designfiles/recursion2.xml6
-rw-r--r--test/resources/design/designfiles/recursion3.xml5
-rw-r--r--test/resources/design/designfiles/returnvaldepend.xml6
-rw-r--r--test/resources/design/designfiles/signatureexceptiondepend.xml6
-rw-r--r--test/resources/design/designfiles/staticdepend.xml6
-rw-r--r--test/resources/design/designfiles/staticfield2depend.xml6
-rw-r--r--test/resources/design/designfiles/staticfielddepend.xml6
-rw-r--r--test/resources/design/designfiles/staticfinaldepend.xml6
-rw-r--r--test/resources/design/designfiles/superdepend.xml6
-rw-r--r--test/resources/design/designfiles/warfailure.xml6
-rw-r--r--test/resources/design/designfiles/warsuccess.xml6
-rw-r--r--test/resources/design/src/mod/arraydepend/ClassDependsOnArray.java32
-rw-r--r--test/resources/design/src/mod/arraydepend2/ClassDependsOnArray.java32
-rw-r--r--test/resources/design/src/mod/arraydepend3/ClassDependsOnArray.java34
-rw-r--r--test/resources/design/src/mod/castdepend/ClassDependsOnCast.java32
-rw-r--r--test/resources/design/src/mod/catchdepend/ClassDependsOnCatch.java37
-rw-r--r--test/resources/design/src/mod/declarejavautil/ClassDependsOnJavaUtil.java30
-rw-r--r--test/resources/design/src/mod/declarejavax/ClassDependsOnJavax.java31
-rw-r--r--test/resources/design/src/mod/dummy/DummyClass.java33
-rw-r--r--test/resources/design/src/mod/dummy/DummyException.java27
-rw-r--r--test/resources/design/src/mod/dummy/DummyInterface.java27
-rw-r--r--test/resources/design/src/mod/dummy/DummyRuntimeException.java27
-rw-r--r--test/resources/design/src/mod/fielddepend/ClassDependsOnField.java31
-rw-r--r--test/resources/design/src/mod/fieldrefdepend/ClassDependsOnReferenceInFieldDeclaration.java31
-rw-r--r--test/resources/design/src/mod/innerclassdepend/InnerClassDependsOnSuper.java32
-rw-r--r--test/resources/design/src/mod/instanceofdepend/ClassDependsOnInstanceOf.java35
-rw-r--r--test/resources/design/src/mod/interfacedepend/ClassDependsOnInterfaceMod2.java31
-rw-r--r--test/resources/design/src/mod/localvardepend/ClassDependsOnLocalVar.java34
-rw-r--r--test/resources/design/src/mod/localvarrefdepend/ClassDependsOnLocalVariableReference.java32
-rw-r--r--test/resources/design/src/mod/newdepend/ClassDependsOnNew.java32
-rw-r--r--test/resources/design/src/mod/newdepend2/ClassDependsOnNewInField.java30
-rw-r--r--test/resources/design/src/mod/nodebugoption/ClassDependsOnLocalVar.java35
-rw-r--r--test/resources/design/src/mod/paramdepend/ClassDependsOnParameter.java32
-rw-r--r--test/resources/design/src/mod/passlocaldepend/ClassDependsOnClassInSamePackage.java30
-rw-r--r--test/resources/design/src/mod/passlocaldepend/FakeClass.java27
-rw-r--r--test/resources/design/src/mod/putstatic/ClassDependsOnNothing.java32
-rw-r--r--test/resources/design/src/mod/recursion/client/ClassDependsOnSubPackage.java32
-rw-r--r--test/resources/design/src/mod/recursion/rec/a/FakeClass.java27
-rw-r--r--test/resources/design/src/mod/recursion2/dependency/Dependency.java27
-rw-r--r--test/resources/design/src/mod/recursion2/rec/client/SubpackageClassDependsOnPackage.java32
-rw-r--r--test/resources/design/src/mod/recursion3/client/SubpackageClassDependsOnSubpackage.java32
-rw-r--r--test/resources/design/src/mod/recursion3/svc/DependencyClass.java27
-rw-r--r--test/resources/design/src/mod/returnvaldepend/ClassDependsOnReturnValue.java32
-rw-r--r--test/resources/design/src/mod/signatureexceptiondepend/ClassDependsOnExceptionInMethodSignature.java32
-rw-r--r--test/resources/design/src/mod/staticdepend/ClassDependsOnStatic.java32
-rw-r--r--test/resources/design/src/mod/staticfield2depend/ClassDependsOnStaticField.java32
-rw-r--r--test/resources/design/src/mod/staticfielddepend/ClassDependsOnStaticField.java32
-rw-r--r--test/resources/design/src/mod/staticfinaldepend/ClassDependsOnConstant.java32
-rw-r--r--test/resources/design/src/mod/superdepend/ClassDependsOnSuperMod2.java30
-rw-r--r--test/resources/design/src/mod/temp/Factory.java32
-rw-r--r--test/resources/design/src/mod/warfailure/ClassDependsOnSuperMod2.java30
-rw-r--r--test/resources/design/src/mod/warsuccess/ClassDependsOnSuperMod2.java30
-rw-r--r--test/resources/design/verifydesign.xml440
-rw-r--r--test/resources/design/web.xml0
-rw-r--r--test/resources/logic/antcallbacktest.xml54
-rw-r--r--test/resources/logic/asserttest.xml86
-rw-r--r--test/resources/logic/foreach.xml104
-rw-r--r--test/resources/logic/if.xml146
-rw-r--r--test/resources/logic/limittest.xml65
-rw-r--r--test/resources/logic/outofdate.xml155
-rw-r--r--test/resources/logic/switch.xml87
-rw-r--r--test/resources/logic/throw.xml15
-rw-r--r--test/resources/logic/timestampselector.xml76
-rw-r--r--test/resources/logic/trycatch.xml108
-rw-r--r--test/resources/math/mathtest.xml22
-rw-r--r--test/resources/platform/osfamily.xml20
-rw-r--r--test/resources/platform/shellscript.xml108
-rw-r--r--test/resources/property/pathtofileset.xml45
-rw-r--r--test/resources/property/propertycopy.xml33
-rw-r--r--test/resources/property/propertyselector.properties7
-rw-r--r--test/resources/property/propertyselector.xml34
-rw-r--r--test/resources/property/variabletest.xml82
-rw-r--r--test/resources/walls/compilewithwalls.xml237
-rw-r--r--test/resources/walls/dependsafter.xml7
-rw-r--r--test/resources/walls/packageB-break.xml9
-rw-r--r--test/resources/walls/testA/mod/modA/ModuleA.java10
-rw-r--r--test/resources/walls/testA/mod/modB/ModuleB.java6
-rw-r--r--test/resources/walls/testB/mod/modA/TestBModuleA.java7
-rw-r--r--test/resources/walls/testB/mod/modB/TestBModuleB.java9
-rw-r--r--test/resources/walls/testC/mod/TestCModule.java11
-rw-r--r--test/resources/walls/testC/mod/modA/TestCModuleA.java7
-rw-r--r--test/resources/walls/testC/mod/modB/TestCModuleB.java7
-rw-r--r--test/resources/walls/walls.xml9
-rw-r--r--test/src/net/sf/antcontrib/BuildFileTestBase.java119
-rw-r--r--test/src/net/sf/antcontrib/antclipse/AntclipseTest.java61
-rw-r--r--test/src/net/sf/antcontrib/antserver/AntServerTest.java127
-rw-r--r--test/src/net/sf/antcontrib/design/VerifyDesignTest.java350
-rw-r--r--test/src/net/sf/antcontrib/logic/AntCallBackTest.java84
-rw-r--r--test/src/net/sf/antcontrib/logic/AssertTest.java84
-rw-r--r--test/src/net/sf/antcontrib/logic/ForeachTaskTest.java99
-rw-r--r--test/src/net/sf/antcontrib/logic/IfTaskTest.java99
-rw-r--r--test/src/net/sf/antcontrib/logic/OutOfDateTest.java110
-rw-r--r--test/src/net/sf/antcontrib/logic/SwitchTest.java87
-rw-r--r--test/src/net/sf/antcontrib/logic/ThrowTaskTest.java41
-rw-r--r--test/src/net/sf/antcontrib/logic/TimestampSelectorTest.java58
-rw-r--r--test/src/net/sf/antcontrib/logic/TryCatchTaskTest.java75
-rw-r--r--test/src/net/sf/antcontrib/math/MathTest.java45
-rw-r--r--test/src/net/sf/antcontrib/platform/OsFamilyTest.java44
-rw-r--r--test/src/net/sf/antcontrib/platform/ShellScriptTest.java165
-rw-r--r--test/src/net/sf/antcontrib/process/LimitTest.java37
-rw-r--r--test/src/net/sf/antcontrib/property/PathToFileSetTest.java66
-rw-r--r--test/src/net/sf/antcontrib/property/PropertyCopyTest.java60
-rw-r--r--test/src/net/sf/antcontrib/property/PropertySelectorTest.java55
-rw-r--r--test/src/net/sf/antcontrib/property/VariableTest.java72
-rw-r--r--test/src/net/sf/antcontrib/walls/CompileWithWallsTest.java330
-rw-r--r--test/src/org/apache/tools/ant/BuildFileTest.java478
275 files changed, 28150 insertions, 0 deletions
diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..02f11bd
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,3 @@
+project.name=ant-contrib
+project.version=1.0
+ivy.deliver.revision=${project.version}
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..c0cabf3
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,202 @@
+<project
+ name="ant-contrib"
+ default="dist"
+ basedir="."
+ xmlns:ivy="antlib:fr.jayasoft.ivy.ant">
+
+ <property file="build.properties" />
+
+ <property name="root.dir" location="." />
+ <property name="src.dir" location="src" />
+ <property name="src.java.dir" location="${src.dir}/java" />
+ <property name="test.dir" location="test" />
+ <property name="test.src.dir" location="${test.dir}/src" />
+ <property name="test.resources.dir" location="${test.dir}/resources" />
+ <property name="docs.dir" location="docs" />
+ <property name="target.dir" location="target" />
+ <property name="target.classes.dir" location="${target.dir}/classes" />
+ <property name="target.test-classes.dir" location="${target.dir}/test-classes" />
+ <property name="target.docs.dir" location="${target.dir}/docs" />
+ <property name="dist.dir" location="dist" />
+ <property name="target.stage.dir" location="${target.dir}/stage" />
+
+ <target name="init">
+ <path id="ivy.lib.path">
+ <fileset dir="lib/ivy/jars" includes="ivy-1.3.1.jar"/>
+ <fileset dir="lib/commons-cli/jars" includes="commons-cli-1.0.jar"/>
+ <fileset dir="lib/commons-codec/jars" includes="commons-codec-1.3.jar"/>
+ <fileset dir="lib/commons-httpclient/jars" includes="commons-httpclient-3.0.1.jar"/>
+ <fileset dir="lib/commons-logging/jars" includes="commons-logging-1.0.4.jar"/>
+ <fileset dir="lib/oro/jars" includes="oro-2.0.8.jar"/>
+ </path>
+
+ <taskdef resource="fr/jayasoft/ivy/ant/antlib.xml"
+ uri="antlib:fr.jayasoft.ivy.ant"
+ classpathref="ivy.lib.path"/>
+ </target>
+
+ <target name="configure" depends="init">
+ <ivy:configure file="ivy-conf.xml" />
+ </target>
+
+ <target name="resolve" depends="configure">
+ <ivy:resolve />
+ </target>
+
+ <target name="classpath" depends="resolve">
+ <ivy:cachepath id="compile.classpath" type="jar" conf="default" />
+ <ivy:cachepath id="test.classpath" type="jar" conf="test" />
+ </target>
+
+ <target name="compile" depends="classpath">
+ <mkdir dir="${target.classes.dir}" />
+ <javac srcdir="${src.java.dir}"
+ destdir="${target.classes.dir}"
+ debug="true"
+ classpathref="compile.classpath"
+ />
+
+ <copy todir="${target.classes.dir}">
+ <fileset dir="${src.java.dir}"
+ includes="**/*.properties,**/*.xml" />
+ </copy>
+ </target>
+
+ <target name="compile-tests" depends="classpath">
+ <mkdir dir="${target.test-classes.dir}" />
+ <javac srcdir="${test.src.dir}"
+ destdir="${target.test-classes.dir}"
+ debug="true">
+ <classpath>
+ <path refid="test.classpath" />
+ <pathelement location="${target.classes.dir}" />
+ </classpath>
+ </javac>
+
+ <copy todir="${target.test-classes.dir}">
+ <fileset dir="${test.src.dir}"
+ includes="**/*.properties,**/*.xml" />
+ <fileset dir="${test.resources.dir}"
+ includes="**/*.java,**/*.properties,**/*.xml" />
+ </copy>
+ </target>
+
+ <target name="jar" depends="compile">
+ <mkdir dir="${target.dir}" />
+ <tstamp>
+ <format property="tstamp" pattern="dd/MM/yyyy HH:mm:ss" />
+ </tstamp>
+ <jar file="${target.dir}/${project.name}.jar">
+ <manifest>
+ <attribute name="Version" value="${project.version}"/>
+ <attribute name="Build-Timestamp" value="${tstamp}"/>
+ </manifest>
+ <fileset dir="${target.classes.dir}" />
+ </jar>
+ </target>
+
+ <target name="clean">
+ <delete includeemptydirs="true">
+ <fileset dir="${target.dir}" includes="**/*" />
+ </delete>
+ </target>
+
+ <target name="javadoc" depends="classpath">
+ <javadoc sourcepath="${src.java.dir}"
+ destdir="${target.docs.dir}/api"
+ packagenames="net.sf.antcontrib.*"
+ author="true"
+ version="true"
+ windowtitle="Ant Contrib"
+ classpathref="compile.classpath">
+ <tag name="ant.task" enabled="false" description="Task:" scope="types"/>
+ <tag name="ant.datatype" enabled="false"
+ description="Data type:" scope="types"/>
+ <tag name="ant.attribute" enabled="false"
+ description="Attribute:" scope="types"/>
+ <tag name="ant.attribute.group" enabled="false"
+ description="Attribute group:" scope="types"/>
+ <tag name="ant.element" enabled="false"
+ description="Nested element:" scope="types"/>
+ </javadoc>
+ </target>
+
+ <target name="docs" depends="javadoc">
+ <mkdir dir="${target.docs.dir}" />
+ <copy todir="${target.docs.dir}">
+ <fileset dir="${docs.dir}" includes="**/*" />
+ </copy>
+ </target>
+
+ <target name="dist-stage" depends="jar,docs">
+ <mkdir dir="${target.stage.dir}" />
+ <mkdir dir="${target.stage.dir}/lib" />
+
+ <copy todir="${target.stage.dir}/${project.name}">
+ <fileset dir="${root.dir}" includes="README.txt" />
+ <fileset dir="${target.dir}" includes="docs/**/*" />
+ </copy>
+ </target>
+
+ <target name="zip" depends="dist-stage">
+ <mkdir dir="${dist.dir}" />
+ <zip file="${dist.dir}/${project.name}-${project.version}-bin.zip">
+ <zipfileset prefix="ant-contrib" dir="${target.stage.dir}"
+ includes="**/*" />
+ </zip>
+
+ <zip file="${dist.dir}/${project.name}-${project.version}-src.zip">
+ <zipfileset prefix="ant-contrib"
+ dir="${root.dir}"
+ includes="**/*"
+ excludes="target,target/**/*,dist,dist/**/*" />
+ </zip>
+ </target>
+
+ <target name="tar.gz" depends="dist-stage">
+ <mkdir dir="${dist.dir}" />
+
+ <tar destfile="${dist.dir}/${project.name}-${project.version}-bin.tar.gz"
+ compression="gzip">
+ <tarfileset prefix="ant-contrib"
+ dir="${target.stage.dir}"
+ includes="**/*" />
+ </tar>
+
+ <tar destfile="${dist.dir}/${project.name}-${project.version}-bin.tar.bz2"
+ compression="bzip2">
+ <tarfileset prefix="ant-contrib"
+ dir="${target.stage.dir}"
+ includes="**/*" />
+ </tar>
+
+ <tar destfile="${dist.dir}/${project.name}-${project.version}-src.tar.gz"
+ compression="gzip">
+ <tarfileset prefix="ant-contrib"
+ dir="${root.dir}"
+ includes="**/*"
+ excludes="target,target/**/*,dist,dist/**/*" />
+ </tar>
+
+ <tar destfile="${dist.dir}/${project.name}-${project.version}-src.tar.bz2"
+ compression="bzip2">
+ <tarfileset prefix="ant-contrib"
+ dir="${root.dir}"
+ includes="**/*"
+ excludes="target,target/**/*,dist,dist/**/*" />
+ </tar>
+
+ </target>
+
+ <target name="package" depends="tar.gz,zip">
+ <checksum fileext=".md5">
+ <fileset dir="${dist.dir}">
+ <include name="*.zip"/>
+ <include name="*.tar.*"/>
+ </fileset>
+ </checksum>
+ </target>
+
+ <target name="dist" depends="package">
+ </target>
+</project> \ No newline at end of file
diff --git a/docs/LICENSE.txt b/docs/LICENSE.txt
new file mode 100644
index 0000000..4d8c2fb
--- /dev/null
+++ b/docs/LICENSE.txt
@@ -0,0 +1,47 @@
+/*
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001-2003 Ant-Contrib project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ * any, must include the following acknowlegement:
+ * "This product includes software developed by the
+ * Ant-Contrib project (http://sourceforge.net/projects/ant-contrib)."
+ * Alternately, this acknowlegement may appear in the software itself,
+ * if and wherever such third-party acknowlegements normally appear.
+ *
+ * 4. The name Ant-Contrib must not be used to endorse or promote products
+ * derived from this software without prior written permission. For
+ * written permission, please contact
+ *
+ * 5. Products derived from this software may not be called "Ant-Contrib"
+ * nor may "Ant-Contrib" appear in their names without prior written
+ * permission of the Ant-Contrib project.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE ANT-CONTRIB PROJECT OR ITS
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ */
diff --git a/docs/manual/index.html b/docs/manual/index.html
new file mode 100644
index 0000000..a5ab022
--- /dev/null
+++ b/docs/manual/index.html
@@ -0,0 +1,91 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-Contrib Tasks</title>
+ </head>
+
+ <body>
+ <h1>Ant-Contrib Tasks</h1>
+
+ <h2>Contents</h2>
+
+ <ul>
+ <li><a href="#intro">What's this?</a></li>
+ <li><a href="#install">Installation</a></li>
+ <li><a href="tasks/index.html">Tasks</a></li>
+ </ul>
+
+ <h2><a name="intro">What's this?</a></h2>
+
+ <p>The Ant-Contrib project is a collection of tasks (and at one
+ point maybe types and other tools) for <a
+ href="http://ant.apache.org/">Apache Ant</a>.</p>
+
+ <p>This Software is distributed under the <a
+ href="LICENSE.txt">Apache Software License</a>.</p>
+
+ <h2><a name="install">Installation</a></h2>
+
+ <p>First you must install Apache Ant itself, most of the
+ Ant-Contrib tasks require Ant 1.5 or higher to work properly,
+ however, there are some tasks, specifically &lt;for&gt; which
+ require Ant 1.6. You can download Ant <a
+ href="http://ant.apache.org/bindownload.cgi">from
+ Apache</a>.</p>
+
+ <p>Then you need the Ant-Contrib tasks themselves. As there is no
+ release of these tasks yet, you have to build them from sources.
+ Fortunately this is easy, check out the sources (grab the
+ <code>ant-contrib</code> module from <a
+ href="http://sourceforge.net/cvs/?group_id=36177">CVS</a>), change
+ into the source directory of ant-contrib and type
+ <code>ant</code>. After Ant has completed, you'll find
+ <code>ant-contrib-version.jar</code> in the <code>lib</code>
+ subdirectory.</p>
+
+ <p>You now have the choice:</p>
+
+ <ol>
+ <li>Copy <code>ant-contrib-version.jar</code> to the
+ <code>lib</code> directory of your Ant installation, or on
+ your CLASSPATH environment variable. If you
+ want to use one of the tasks in your project, add the line
+<pre>
+&lt;taskdef resource=&quot;net/sf/antcontrib/antlib.xml&quot;/&gt;
+</pre>
+ to your build file.</li>
+
+<br />
+<br />
+
+ <li>Keep <code>ant-contrib-version.jar</code> in a separate
+ location. You now have to tell Ant explicitly where to find it
+ (say in <code>/usr/share/java/lib</code>):
+<pre>
+&lt;taskdef resource=&quot;net/sf/antcontrib/antlib.xml&quot;&gt;
+ &lt;classpath&gt;
+ &lt;pathelement location=&quot;/usr/share/java/lib/ant-contrib-version.jar&quot;/&gt;
+ &lt;/classpath&gt;
+&lt;/taskdef&gt;
+</pre>
+ </li>
+
+ <li>If you would like to use run with Ant Version 1.5 you must use the
+ the .properties file instead. Keep in mind that some tasks will not
+ be available to you , such as the &lt;for&gt; task:
+
+<pre>
+&lt;taskdef resource=&quot;net/sf/antcontrib/antcontrib.properties&quot;&gt;
+ &lt;classpath&gt;
+ &lt;pathelement location=&quot;/usr/share/java/lib/ant-contrib-version.jar&quot;/&gt;
+ &lt;/classpath&gt;
+&lt;/taskdef&gt;
+</pre>
+
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/antcallback_task.html b/docs/manual/tasks/antcallback_task.html
new file mode 100644
index 0000000..731e7c4
--- /dev/null
+++ b/docs/manual/tasks/antcallback_task.html
@@ -0,0 +1,177 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+<title>
+AntCallBack</title>
+
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+
+<link rel="home" href="index.html" title="Antelope Users Guide">
+
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+
+<link rel="previous" href="bk03ch14.html" title="Chapter&nbsp;14.&nbsp;AntFetch">
+
+<link rel="next" href="bk03ch16.html" title="Chapter&nbsp;16.&nbsp;Call Task">
+
+</head>
+
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="antcallback">
+</a>
+AntCallBack</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+AntCallBack is identical to the standard 'antcall' task, except that it allows properties set in the called target to be available in the calling target.
+</p>
+<p>
+
+</p>
+<p>
+
+Some background may be in order: When the &lt;antcall&gt; task is used, in actuality, a new Ant project is created, and depending on the inheritAll property, it is populated with properties from the original project. Then the requested target in this new project is executed. Any properties set in the new project remain with that project, they do not get "passed back" to the original project. So, for example, if the target in the new project sets a property named "image.directory", there is no reference to that property in the original. Here's an example of what I mean:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;target name="testCallback" description="Test CallBack"&gt;
+ &lt;antcallback target="-testcb" return="a, b"/&gt;
+ &lt;echo&gt;a = ${a}&lt;/echo&gt;
+ &lt;echo&gt;b = ${b}&lt;/echo&gt;
+ &lt;/target&gt;
+
+ &lt;target name="-testcb"&gt;
+ &lt;property name="a" value="A"/&gt;
+ &lt;property name="b" value="B"/&gt;
+ &lt;/target&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+The output from executing "testCallback" looks like this:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+a = A
+b = B
+</pre>
+</td>
+</tr>
+</table>
+
+Contrast with this output from "antcall":
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+a = ${a}
+b = ${b}
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+This is an often requested feature for Ant, at least judging from the Ant mailing lists. I assume this is because it allows a more functional programming style than Ant natively supports. The proper Ant way of doing the above is like this:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;target name="testCallback" description="Test CallBack" depends="-testcb"&gt;
+ &lt;echo&gt;a = ${a}&lt;/echo&gt;
+ &lt;echo&gt;b = ${b}&lt;/echo&gt;
+ &lt;/target&gt;
+
+ &lt;target name="-testcb"&gt;
+ &lt;property name="a" value="A"/&gt;
+ &lt;property name="b" value="B"/&gt;
+ &lt;/target&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+This is actually looks cleaner in this situation, and is faster, too. There is significant overhead in using both "antcall" and "antcallback" in that they both require a lot of object instantiation and property copying. That said, many people prefer to use "antcall" and "antcallback" as it better fits their logic and style.
+</p>
+<p>
+
+The attributes for AntCallBack are identical to the 'antcall' task, with one additional, optional attibute. This attribute is named "return" and can be either a single property name or a comma separated list of property names.
+<div class="table">
+<a name="N10B76">
+</a>
+<p class="title">
+<b>
+Table&nbsp;15.1.&nbsp;AntCallBack Attributes</b>
+</p>
+<table summary="AntCallBack Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+return</td>
+<td>
+A comma separated list of property names. Whitespace is allowed, so either "a,b" or "a, b" are acceptable.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+For other attribute and nested element information and more examples, see the documentation for the "antcall" task in the Ant documentation.
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/antclipse_task.html b/docs/manual/tasks/antclipse_task.html
new file mode 100644
index 0000000..8ac5667
--- /dev/null
+++ b/docs/manual/tasks/antclipse_task.html
@@ -0,0 +1,139 @@
+<html lang="en-us">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Antclipse Task</title>
+</head>
+
+<body>
+
+<h2>Antclipse Task</h2>
+<p>Creator: Adrian Spinei (<a href="mailto:[email protected]">[email protected]</a>)</p>
+<h3>Description</h3>
+<p>UNSTABLE CODE, some parameters are supposed to change</p>
+<p>This task creates classpaths or filesets based on your current .classpath file generated by Eclipse</p>
+<p>Classpath creation is simple, it just produces a classpath that you can subsequently retrieve by its refid.
+The filesets are a little trickier, because the task is producing a fileset per directory in the case of sources and another separate fileset for the
+output file. Which is not necessarily bad, since the content of each directory usually serves a different purpose. Now, in order to avoit conflicting
+refids each fileset has a name composed by the idcontainer, followed by a dash and postfixed by the path. Supposing that your output path is
+<b>bin/classes</b> and the idcontainer is default, the task will create a fileset with refid &quot;<b>antclipse-bin/classes</b>&quot;. The fileset will include all the files contained in
+your output directory, but without the trailing path bin/classes (as you usually strip it when creating the distribution jar).</p>
+<p>If you have two source directories, called src and test, you'll be provided with two filesets, with refids like <b>antclipse-src<b> and </b>antclipse-test</b>.
+However, you don't have to code manually the path since some properties are created as a "byproduct" each time you execute the task. Their name is "<b>idref</b>"
+postfixed by "<b>outpath</b>" and "<b>srcpath</b>" (in the case of the source, you'll find the location of the first source directory).</p>
+
+<h3>Parameters</h3>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td>Attribute</td>
+ <td>Description</td>
+
+ <td>Required</td>
+ </tr>
+ <tr>
+ <td><em>produce</em></td>
+ <td>This parameter tells the task wether to produce a "classpath" or a "fileset" (multiple filesets, as a matter of fact).</td>
+ <td>Yes</td>
+ </tr>
+
+ <tr>
+ <td><em>idcontainer</em></td>
+ <td>The refid which will serve to identify the deliverables. When multiple filesets are produces, their refid is a concatenation between this value and something else (usually obtained from a path). Default "antclipse"</td>
+ <td>No</td>
+ </tr>
+ <tr>
+ <td><em>includelibs</em></td>
+
+ <td>Boolean, whether to include or not the project libraries. Default is true.</td>
+ <td>No</td>
+ </tr>
+ <tr>
+ <td><em>includesource</em></td>
+ <td>Boolean, whether to include or not the project source directories. Default is false.</td>
+ <td>No</td>
+
+ </tr>
+ <tr>
+ <td><em>includeoutput</em></td>
+ <td>Boolean, whether to include or not the project output directories. Default is false.</td>
+ <td>No</td>
+ </tr>
+ <tr>
+
+ <td><em>verbose</em></td>
+ <td>Boolean, telling the app to throw some info during each step. Default is false.</td>
+ <td>No</td>
+ </tr>
+ <tr>
+ <td><em>includes</em></td>
+ <td>A regexp for files to include. It is taken into account only when producing a classpath, doesn't work on source or output files. It is a real regexp, not a "*" expression.</td>
+
+ <td>No</td>
+ </tr>
+ <tr>
+ <td><em>excludes</em></td>
+ <td>A regexp for files to exclude. It is taken into account only when producing a classpath, doesn't work on source or output files. It is a real regexp, not a "*" expression.</td>
+ <td>No</td>
+ </tr>
+
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+<p>None at the moment.</p>
+
+<h3>TODOS</h3>
+<ul>
+<li>make "includes" and "excludes" to work on the source and output filesets</li>
+<li>maybe find an elegant solution to this multiple fileset/directories issues</li>
+<li>work with files referenced in other projects</li>
+</ul>
+
+<h3>Example</h3>
+
+<p>This is a pretty self-explanatory Ant script, just follow the comments.</p>
+
+<pre>
+<span style='color:#7f0055; '>&lt;?</span><span style='color:#7f0055; '>xml</span> <span style='color:#7f0055; '>version</span>="1.0"<span style='color:#7f0055; '>?></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>project</span> default=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>compile</span><span style='color:#2a00ff; '>"</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>test</span><span style='color:#2a00ff; '>"</span> basedir=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>.</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>taskdef</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>antclipse</span><span style='color:#2a00ff; '>"</span> classname=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>net.sf.antcontrib.antclipse.ClassPathTask</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>target</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>make.fs.output</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> creates a fileset including all the files from the output directory, called ecl1-bin if your binary directory is bin/ </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; '>antclipse</span> produce=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>fileset</span><span style='color:#2a00ff; '>"</span> idcontainer=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl1</span><span style='color:#2a00ff; '>"</span> includeoutput=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span> includesource=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>false</span><span style='color:#2a00ff; '>"</span>
+ includelibs=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>false</span><span style='color:#2a00ff; '>"</span> verbose=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>target</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>target</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>make.fs.sources</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> creates a fileset for each source directory, called ecl2-*source-dir-name*/ </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; '>antclipse</span> produce=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>fileset</span><span style='color:#2a00ff; '>"</span> idcontainer=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl2</span><span style='color:#2a00ff; '>"</span> includeoutput=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>false</span><span style='color:#2a00ff; '>"</span> includesource=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span>
+ includelibs=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>false</span><span style='color:#2a00ff; '>"</span> verbose=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>target</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>target</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>make.fs.libs</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> creates a fileset sontaining all your project libs called ecl3/ </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; '>antclipse</span> produce=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>fileset</span><span style='color:#2a00ff; '>"</span> idcontainer=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl3</span><span style='color:#2a00ff; '>"</span> verbose=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>target</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>target</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>make.cp</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> creates a fileset sontaining all your project libs called ecl3/ </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; '>antclipse</span> produce=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>classpath</span><span style='color:#2a00ff; '>"</span> idcontainer=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>eclp</span><span style='color:#2a00ff; '>"</span> verbose=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span> includeoutput=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>true</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>target</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>target</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>compile</span><span style='color:#2a00ff; '>"</span> depends=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>make.fs.libs, make.fs.output, make.fs.sources, make.cp</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>echo</span> message=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>The output path is $</span><span style='color:#2a00ff; '>{ecl1outpath}</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>echo</span> message=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>The source path is $</span><span style='color:#2a00ff; '>{ecl2srcpath}</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> makes a jar file with the content of the output directory </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>zip</span> destfile=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>out.jar</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span><span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>fileset</span> refid=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl1-${</span><span style='color:#2a00ff; '>ecl1outpath}</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span><span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>zip</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> makes a zip file with all your sources (supposing you have only source directory) </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>zip</span> destfile=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>src.zip</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span><span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>fileset</span> refid=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl2-${</span><span style='color:#2a00ff; '>ecl2srcpath}</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span><span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>zip</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> makes a big zip file with all your project libraries </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>zip</span> destfile=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>libs.zip</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>></span><span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>fileset</span> refid=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>ecl3</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span><span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>zip</span><span style='color:#7f0055; '>></span>
+ <span style='color:#3f7f59; '>&lt;!--</span><span style='color:#3f7f59; '> imports the classpath into a property then echoes the property </span><span style='color:#3f7f59; '>--></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>property</span> name=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>cpcontent</span><span style='color:#2a00ff; '>"</span> refid=<span style='color:#2a00ff; '>"</span><span style='color:#2a00ff; '>eclp</span><span style='color:#2a00ff; '>"</span><span style='color:#7f0055; '>/></span>
+ <span style='color:#7f0055; '>&lt;</span><span style='color:#7f0055; font-weight:bold; '>echo</span><span style='color:#7f0055; '>></span>The newly created classpath is ${cpcontent}<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>echo</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>target</span><span style='color:#7f0055; '>></span>
+<span style='color:#7f0055; '>&lt;/</span><span style='color:#7f0055; font-weight:bold; '>project</span><span style='color:#7f0055; '>></span>
+</pre>
+
+<hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</body>
+</html>
+
diff --git a/docs/manual/tasks/antfetch_task.html b/docs/manual/tasks/antfetch_task.html
new file mode 100644
index 0000000..f92e635
--- /dev/null
+++ b/docs/manual/tasks/antfetch_task.html
@@ -0,0 +1,151 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+AntFetch</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch13.html" title="Chapter&nbsp;13.&nbsp;SSH and SCP">
+<link rel="next" href="bk03ch15.html" title="Chapter&nbsp;15.&nbsp;AntCallBack">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="antfetch">
+</a>
+AntFetch</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+AntFetch is identical to the standard 'Ant' task, except that it allows properties from the new project to be set in the original project.
+</p>
+<p>
+
+</p>
+<p>
+
+Some background may be in order: When the &lt;ant&gt; task is used, in actuality, a new Ant project is created, and depending on the inheritAll property, it is populated with properties from the original project. Then the target in this new project is executed. Any properties set in the new project remain with that project, they do not get "passed back" to the original project. So, for example, if the target in the new project sets a property named "image.directory", there is no reference to that property in the original. Here's an example of what I mean:
+</p>
+<p>
+
+Suppose that the "fillImageDirectory" target sets a property named "image.directory" and I call the following:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;ant dir="${image.project} target="fillImageDirectory"/&gt;
+ &lt;echo&gt;${image.directory}&lt;/echo&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+The output of the echo task will be ${image.directory}, not whatever was set in the "fillImageDirectory" target.
+</p>
+<p>
+
+The AntFetch task allows that image.directory property to be set in the original project. The attributes for AntFetch are identical to the 'Ant' task, with one additional, optional attibute. This attribute is named "return" and can be either a single property name or a comma separated list of property names.
+</p>
+<p>
+
+Assuming that "fillImageDirectory" actually sets a property named "image.directory", the following example will print out the directory name:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;antfetch dir="${image.project} target="fillImageDirectory" return="image.directory"/&gt;
+ &lt;echo&gt;${image.directory}&lt;/echo&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+And this one will also print out the thumbnail directory:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;antfetch dir="${image.project} target="fillImageDirectory" return="image.directory, thumbnail.directory"/&gt;
+ &lt;echo&gt;${image.directory}&lt;/echo&gt;
+ &lt;echo&gt;${thumbnail.directory}&lt;/echo&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+The attributes for AntFetch are identical to the 'ant' task, with one additional, optional attibute. This attribute is named "return" and can be either a single property name or a comma separated list of property names.
+<div class="table">
+<a name="N10B35">
+</a>
+<p class="title">
+<b>
+Table&nbsp;14.1.&nbsp;AntFetch Attributes</b>
+</p>
+<table summary="AntFetch Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+return</td>
+<td>
+A comma separated list of property names. Whitespace is allowed, so either "a,b" or "a, b" are acceptable.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+For other attribute and nested element information and more examples, see the documentation for the "ant" task in the Ant documentation.
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/assert_task.html b/docs/manual/tasks/assert_task.html
new file mode 100644
index 0000000..7d375ce
--- /dev/null
+++ b/docs/manual/tasks/assert_task.html
@@ -0,0 +1,260 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Assert Task</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch03.html" title="Chapter&nbsp;3.&nbsp;Installation">
+<link rel="next" href="bk03ch05.html" title="Chapter&nbsp;5.&nbsp;If Task">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="Assert">
+</a>
+Assert Task</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The Assert task adds an assertion capability to Ant projects. This task works in a manner very similar to the Java <tt class="computeroutput">
+assert</tt>
+ keyword, and provides a limited "design by contract" facility to Ant. This is very useful for testing build scripts prior to putting them into production.
+</p>
+<p>
+
+The Assert task verifies that a given property has a
+given value and throws a BuildException if the property value is not as expected
+or the property does not exist.
+</p>
+<p>
+
+Also like Java's <tt class="computeroutput">
+assert</tt>
+ keyword, the Assert task must be 'turned on' using the property <tt class="computeroutput">
+ant.enable.asserts</tt>
+. If not set, or is set to <tt class="computeroutput">
+false</tt>
+, the Assert task works exactly like the Sequential task. If the <a href="variable_task.html" title="Variable Task">
+Variable task</a>
+ is used to define this property, then it can be turned on and off as needed throughout a build.
+</p>
+<p>
+
+This task can hold other tasks including Assert.
+</p>
+<p>
+
+The Assert task may contain one 'bool' element. The 'bool' element is identical to the ConditionTask, but unlike the ConditionTask, is actually a Task. The 'bool' element can contain all the conditions permitted by the ConditionTask, plus the <a href="bk03ch05s02.html" title="More Conditions">
+IsPropertyTrue</a>
+, <a href="more_conditions.html" title="More Conditions">
+IsPropertyFalse</a>
+,
+<a href="more_conditions.html" title="More Conditions">
+StartsWith</a>
+,
+<a href="more_conditions.html" title="More Conditions">
+EndsWith</a>
+,
+<a href="more_conditions.html" title="More Conditions">
+IsGreaterThan</a>
+,
+<a href="more_conditions.html" title="More Conditions">
+IsLessThan</a>
+ and conditions.
+See the If task for examples of using these conditionals.
+</p>
+
+<p>
+
+<div class="table">
+<a name="N10583">
+</a>
+<p class="title">
+<b>
+Table&nbsp;4.1.&nbsp;Assert Task Attributes</b>
+</p>
+<table summary="Assert Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+name</td>
+<td>
+The name of the property to test for.</td>
+<td>
+none</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+exists</td>
+<td>
+Test for existence or non-existence of the property.</td>
+<td>
+True</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+value</td>
+<td>
+The value to test for, implies 'exists=true'. If the value in the project is different than this value, a BuildException will be thrown and the build will stop.</td>
+<td>
+none</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+execute</td>
+<td>
+Should the tasks contained in this task be executed? It may be useful to set this to false when testing build files.</td>
+<td>
+True</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+failonerror</td>
+<td>
+Should the build halt if the assertion fails? Setting this to false is contrary to the intented use of assertions, but may be useful in certain situations. </td>
+<td>
+True</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+
+</p>
+<p>
+
+As stated above, the Assert task may contain a nested "bool" task, otherwise,
+the Assert task does not support any nested
+elements apart from Ant tasks. Any valid Ant task may be embedded within the
+assert task.
+</p>
+<p>
+
+In the following example, the first <tt class="computeroutput">
+assert</tt>
+ task checks that the <tt class="computeroutput">
+wait</tt>
+ property exists and does not execute the <tt class="computeroutput">
+echo</tt>
+ and <tt class="computeroutput">
+sleep</tt>
+ tasks. The second <tt class="computeroutput">
+assert</tt>
+ task checks that the <tt class="computeroutput">
+wait</tt>
+ property exists, has a value of 2, and executes the <tt class="computeroutput">
+echo</tt>
+ task.
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="wait" value="2"/&gt;
+ &lt;assert name="wait" execute="false"&gt;
+ &lt;echo&gt;
+ Waiting ${wait} seconds...
+ Click the red button to stop waiting.
+ &lt;/echo&gt;
+ &lt;sleep seconds="${wait}"/&gt;
+ &lt;/assert&gt;
+ &lt;assert name="wait" value="2" execute="true"&gt;
+ &lt;echo&gt;done waiting!&lt;/echo&gt;
+ &lt;/assert&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+The next example shows Assert being used in a unit test for the "limit" task:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="ant.enable.asserts" value="true"/&gt;
+ &lt;target name="test2"&gt;
+ &lt;!-- should not stop 'sleep' task, should print out '_passed_' --&gt;
+ &lt;stopwatch name="timer"/&gt;
+ &lt;limit maxwait="5"&gt;
+ &lt;sleep seconds="1"/&gt;
+ &lt;echo&gt;_passed_&lt;/echo&gt;
+ &lt;/limit&gt;
+ &lt;stopwatch name="timer" action="total"/&gt;
+ &lt;assert message="Too much time."&gt;
+ &lt;bool&gt;
+ &lt;islessthan arg1="${timer}" arg2="2"/&gt;
+ &lt;/bool&gt;
+ &lt;/assert&gt;
+ &lt;/target&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+If the <tt class="computeroutput">
+ant.enable.asserts</tt>
+ property is set to false, then in the above example, the <tt class="computeroutput">
+echo</tt>
+, <tt class="computeroutput">
+sleep</tt>
+, and <tt class="computeroutput">
+echo</tt>
+ tasks will all execute.
+</p>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</div>
+</body>
+</html>
diff --git a/docs/manual/tasks/compilewithwalls.html b/docs/manual/tasks/compilewithwalls.html
new file mode 100644
index 0000000..c3416cb
--- /dev/null
+++ b/docs/manual/tasks/compilewithwalls.html
@@ -0,0 +1,135 @@
+<html lang="en-us">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>Compile With Walls Task</title>
+</head>
+
+<body>
+
+<h2><a name="javac">Compile With Walls Task</a></h2>
+
+<h3>Deprecated: Use <a href="verifydesign.html">verifydesign</a> task instead</h3>
+<p>Creator: Dean Hiller (<a href="mailto:[email protected]">[email protected]</a>)</p>
+<h3>Description</h3>
+<p>Puts up walls in a the same source tree to ensure that designs are not violated</p>
+<p>This task helps someone separate out packages and prevent dependencies from occurring on accident. For example, if there are three packages in one source tree
+<ul>
+<li>biz.xsoftware.mod</li>
+<li>biz.xsoftware.modA</li>
+<li>biz.xsoftware.modB</li>
+</ul>
+and modB and modA should be able to compiled independently, you can put a wall up in between the two so that if anyone adds a dependency between modA and modB, the build will break. This is particularly good if the builds are automated.</p>
+
+<p>This task is for low level design. For architectural walls like client and server, I would suggest using multiple source trees and compiling those source trees independently as two different ant compile targets.</p>
+
+One pattern I personally like to follow can be seen on the vmaster project on sourceforge. Instructions to check it out and look at are <a href="https://sourceforge.net/cvs/?group_id=46703">HERE.</a> The interesting files in vmaster to look at our here....
+<ul>
+<li>vmaster/vmasterdiff/conf/build.xml(ant file using compilewithwalls)</li>
+<li>vmaster/vmasterdiff/conf/dependencies.xml(The compilewithwalls task references this file as the walls)</li>
+</ul>
+Looking at some of the 2nd file(dependencies.xml), one can see apis separated out for many non-GUI and GUI components in these packages
+<ul>
+<li>api.biz.xsoftware.difflib.file.*</li>
+<li>api.biz.xsoftware.difflib.dir.*</li>
+<li> more api.* packages</li>
+<li>org.vmasterdiff.gui.dirdiff.impl.*</li>
+</ul>
+Looking closely at the api.* packages, each one has a Factory. This factory uses reflection to create the implementation components. Basically, the api should not know of the implementation so there are walls around the api. Reflection to instantiate the implementation gets around these walls. My bigger components that use the smaller one's use these factories. In my design you are guaranteed these components are replaceable. Feel free to checkout vmaster and look at the factories also.
+<p>
+
+<h3>Parameters</h3>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">walls</td>
+ <td valign="top">Specifies the external dependency file to use(see example below)</td>
+ <td align="center" valign="top">Either this or a nested walls element is required</td>
+ </tr>
+ <tr>
+ <td valign="top">intermediaryBuildDir</td>
+ <td valign="top">Specifies scratch area for the compilewithwalls task to do the building and ensure dependencies are not violated</td>
+ <td align="center" valign="top">required</td>
+ </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+<p>This task can contain one nested javac task and one nested walls task. See the <a href="PUT JAVAC REF HERE">javac task</a> for it's attributes and nested elements.
+
+</p>
+<h3>Walls element</h3>
+<p>
+The nested walls element or the walls attribute must be specified. Only one may be used. The walls element contains nested package elements. These nested package elements have the following attributes. If any package depends on another, it must be listed after the package it depends on in the walls element.
+</p>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">name</td>
+ <td valign="top">A smaller nickname for the package to reference in depends</td>
+ <td align="center" valign="top">Required</td>
+ </tr>
+ <tr>
+ <td valign="top">package</td>
+ <td valign="top">The package to compile such as biz.xsoftware.* to
+ include the immediate package only or
+ biz.xsoftware.** to include biz.xsoftware and all subpackages.</td>
+ <td align="center" valign="top">Required</td>
+ </tr>
+ <tr>
+ <td valign="top">depends</td>
+ <td valign="top">If a package need one of the previously specified packages to compile, it's name would be added here in a comma separated list. For example depends="modA,modB"</td>
+ <td align="center" valign="top">Optional</td>
+ </tr>
+</table>
+
+<h3>Examples</h3>
+
+In the examples, I will show the javac as a null element, because it's use is documented in the <a href="PUT JAVAC REF HERE">javac task</a> documentation.
+
+<h4>Walls Nested Element....</h4>
+<pre>
+ &lt;compilewithwalls&gt;
+ &lt;walls&gt;
+ &lt;package name=&quot;modA&quot; package=&quot;biz.xsoftware.mod.modA.**&quot;/&gt;
+ &lt;package name=&quot;modB&quot; package=&quot;biz.xsoftware.mod.modB.*&quot;/&gt;
+ &lt;package name=&quot;mod&quot; package=&quot;biz.xsoftware.mod.modA.*&quot; depends=&quot;modA,modB&quot;/&gt;
+ &lt;/walls&gt;
+ <a href="PUT JAVAC TASK LINK HERE">&lt;javac&gt;&lt;/javac&gt;</a>
+ &lt;/compilewithwalls&gt;</pre>
+<p>
+Notice that the package named mod had to come after the packages it depended on. Now if anybody puts code in modA that uses classes in modB, the build will break telling them they are violating a design constraint. I personally have had many a devoloper accidentally put dependencies in that we agreed in the design should not be there. This includes myself. This prevents this from happening as long as someone doesn't change the ant build file....If someone does though, at least you can view the package dependencies and now what they are.
+</p>
+
+<h4>Walls attribute......</h4>
+<pre>
+These next lines would be in build.xml.....
+ &lt;compilewithwalls walls="dependencies.xml"&gt;
+ <a href="PUT JAVAC TASK LINK HERE">&lt;javac&gt;&lt;/javac&gt;</a>
+ &lt;/compilewithwalls&gt;</pre>
+
+<pre>
+These lines would be in dependencies.xml.....
+ &lt;walls&gt;
+ &lt;package name=&quot;modA&quot; package=&quot;biz.xsoftware.mod.modA.**&quot;/&gt;
+ &lt;package name=&quot;modB&quot; package=&quot;biz.xsoftware.mod.modB.*&quot;/&gt;
+ &lt;package name=&quot;mod&quot; package=&quot;biz.xsoftware.mod.modA.*&quot; depends=&quot;modA,modB&quot;/&gt;
+ &lt;/walls&gt;</pre>
+
+
+
+
+<hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</body>
+</html>
+
diff --git a/docs/manual/tasks/for.html b/docs/manual/tasks/for.html
new file mode 100644
index 0000000..ecf23fe
--- /dev/null
+++ b/docs/manual/tasks/for.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: For</title>
+ </head>
+
+ <body>
+ <h1>For</h1>
+
+ <p>The for task iterates over a list, a list of paths, or
+ any type that has a public iterator() method.
+ The list will be evaluated first.
+ Nested paths are evaluated in the order they
+ appear in the task.
+ Nested types will then be evalulated.
+ </p>
+ <p>
+ This task is the same as the &lt;foreach&gt; task, except that
+ <ul>
+ <li>it uses a nested sequential for each iteration; and
+ <li>it implements an additional &quot;keepgoing&quot; attribute.
+ </ul>
+ &lt;for&gt; makes use of ant's macrodef task, so the @{} notation
+ is used for parameter substition.
+ </p>
+ <p><em>
+ This task only works for ant version greater than or equal
+ to ant 1.6.0.
+ </em>
+ </p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">list</td>
+ <td valign="top">The list of values to process, with the
+ delimiter character, indicated by the &quot;delimiter&quot;
+ attribute, separating each value.</td>
+ <td align="center" valign="top">Yes, unless a nested path
+ has been specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">param</td>
+ <td valign="top">Name of the parameter to pass the tokens or
+ files in as to the sequential.</td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">delimiter</td>
+ <td valign="top">The delimiter characters that separates the
+ values in the &quot;list&quot; attribute. Each character in the
+ supplied string can act as a delimiter. This follows the semantics
+ of the StringTokenizer class.</td>
+ <td align="center" valign="top">No, defaults to &quot;,&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">parallel</td>
+ <td valign="top">If <code>true</code>, all iterations of the nested
+ &lt;sequential&gt;
+ will execute in parallel. Defaults to <code>false</code>,
+ which forces sequential execution of the iterations. It is up to
+ the caller to ensure that parallel execution is safe.
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">keepgoing</td>
+ <td valign="top">If <code>true</code>, all iterations of the called
+ &lt;sequential&gt; will be executed, even if a task in one or more of them fails.
+ Defaults
+ to <code>false</code>, which forces execution to stop as soon as a
+ task fails. At the end, if any iterator has failed, the &lt;for&gt;
+ task will fail, otherwise &lt;for&gt; will succeed.
+ <p>
+ Note that execution does not proceed keepgoing from one task
+ to the next within the &lt;sequential&gt, but rather from one iteration to the
+ next.
+ </p>
+ <p>It is up to the caller to ensure that keepgoing execution is safe.</p>
+ </td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">threadCount</td>
+ <td valign="top">The maximum number of allowable threads when executing
+ in parallel.
+ <td align="center" valign="top">No. Defaults to 5.</td>
+ </tr>
+ <tr>
+ <td valign="top">trim</td>
+ <td valign="top">If <code>true</code>, any leading or trailing
+ whitespace will be removed from the list item before it is passed
+ to the sequential.
+ </td>
+ <td align="center" valign="top">No. Defaults to false.</td>
+ </tr>
+ </table>
+
+ <h2>Parameters specified as nested elements</h2>
+
+ <a name="path"><h3>path</h3></a>
+
+ <p><a href="http://ant.apache.org/manual/using.html#path">Path</a>s
+ are used to select sets of files or directories to iterate over.</p>
+
+ <p>Using a path allows you to determine the order by which files
+ are considered by using
+ <a href="http://ant.apache.org/manual/CoreTypes/filelist.html">filelist</a>s
+ or explicit <code>pathelements</code>. You also can specify
+ whether you want to iterate over files or directories by chosing
+ either filesets or
+ <a href="http://ant.apache.org/manual/CoreTypes/dirset.html">dirset</a>s.</p>
+ <a name="fileset"><h3>fileset</h3></a>
+ <p><a href="http://ant.apache.org/manual/CoreTypes/fileset.html">FileSet</a>s
+ are used to select sets of files to iterate over.
+ </p>
+ <a name="fileset"><h3>dirset</h3></a>
+ <p><a href="http://ant.apache.org/manual/CoreTypes/dirset.html">DirSet</a>s
+ are used to select sets of directories to iterate over.
+ </p>
+
+ <a name="seqential"><h3>sequential</h3></a>
+ This is the list of tasks to be run for each iteration of
+ the list.
+ <h3>Example</h3>
+ <p>
+ To print out the first five letters of the latin alphabet:
+ </p>
+ <blockquote>
+ <pre>
+&lt;echo message="The first five letters of the alphabet are:"/&gt;
+&lt;for list="a,b,c,d,e" param="letter"&gt;
+ &lt;sequential&gt;
+ &lt;echo&gt;Letter @{letter}&lt;/echo&gt;
+ &lt;/sequential&gt;
+&lt;/for&gt;
+ </pre>
+ </blockquote>
+ <p>
+ A more complicated example to to iterate over a set
+ of c++ source files and invoke the &lt;cc&gt; task on them:
+ </p>
+ <blockquote>
+ <pre>
+&lt;for param="file"&gt;
+ &lt;path&gt;
+ &lt;fileset dir="${test.dir}/mains" includes="*.cpp"/&gt;
+ &lt;/path&gt;
+ &lt;sequential&gt;
+ &lt;propertyregex override="yes"
+ property="program" input="@{file}"
+ regexp=".*/([^\.]*)\.cpp" replace="\1"/&gt;
+ &lt;mkdir dir="${obj.dir}/${program}"/&gt;
+ &lt;mkdir dir="${build.bin.dir}"/&gt;
+ &lt;cc link="executable" objdir="${obj.dir}/${program}"
+ outfile="${build.bin.dir}/${program}"&gt;
+ &lt;compiler refid="compiler.options"/&gt;
+ &lt;fileset file="@{file}"/&gt;
+ &lt;linker refid="linker-libs"/&gt;
+ &lt;/cc&gt;
+ &lt;/sequential&gt;
+&lt;/for&gt;
+ </pre>
+ </blockquote>
+ The preceding example will stop as soon as one of the &lt;cc&gt; tasks fails.
+ If you change the first line of the example to
+ <pre> &lt;for param="file" keepgoing="true"&gt;</pre>
+ All iterations will be executed, and then &lt;for&gt; will fail if any one
+ or more of the &lt;cc&gt; tasks failed.
+ <p>
+ The following example embeds an outofdate type and iterates over
+ the sources that are newer than their corresponding targets.
+ </p>
+
+ <pre>
+ &lt;ac:for param="xmlfile" xmlns:ac="antlib:net.sf.antcontrib"&gt;
+ &lt;ac:outofdate&gt;
+ &lt;ac:sourcefiles&gt;
+ &lt;ac:fileset dir="${basedir}/xdocs" includes="**/*.xml"/&gt;
+ &lt;/ac:sourcefiles&gt;
+ &lt;ac:mapper dir="${basedir}/xdocs"
+ type="glob" from="*.xml" to="${basedir}/docs/*.html"/&gt;
+ &lt;/ac:outofdate&gt;
+ &lt;ac:sequential&gt;
+ &lt;echo&gt;Need to generate a target html file from source file @{xmlfile}&lt;/echo&gt;
+ &lt;/ac:sequential&gt;
+ &lt;/ac:for&gt;
+ </pre>
+ <hr>
+ <p align="center">Copyright &copy; 2003-2005 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/foreach.html b/docs/manual/tasks/foreach.html
new file mode 100644
index 0000000..d3f6b0b
--- /dev/null
+++ b/docs/manual/tasks/foreach.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Foreach</title>
+ </head>
+
+ <body>
+ <h1>Foreach</h1>
+
+ <p>The foreach task iterates over a list, a list of paths, or
+ both. If both, list and paths, are specified, the list will be
+ evaluated first. Nested paths are evaluated in the order they
+ appear in the task.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">list</td>
+ <td valign="top">The list of values to process, with the
+ delimiter character, indicated by the &quot;delimiter&quot;
+ attribute, separating each value.</td>
+ <td align="center" valign="top">Yes, unless a nested Fileset
+ has been specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">target</td>
+ <td valign="top">Name of the target to call for each token or
+ matched file.</td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">param</td>
+ <td valign="top">Name of the parameter to pass the tokens or
+ files in as to the target.</td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">delimiter</td>
+ <td valign="top">The delimiter characters that separates the
+ values in the &quot;list&quot; attribute. Each character in the
+ supplied string can act as a delimiter. This follows the semantics
+ of the StringTokenizer class.</td>
+ <td align="center" valign="top">No, defaults to &quot;,&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">inheritall</td>
+ <td valign="top">If <code>true</code>, pass all properties to
+ the called target. Defaults to <code>false</code>.</td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">inheritrefs</td>
+ <td valign="top">If <code>true</code>, pass all references to the
+ the called target. Defaults to <code>false</code>.</td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">parallel</td>
+ <td valign="top">If <code>true</code>, all instances of the called
+ target will execute in parallel. Defaults to <code>false</code>,
+ which forces sequential execution of the targets. It is up to
+ the caller to ensure that parallel execution is safe. This is
+ accomplished through the means of the "parallel" task contained
+ in the ANT core.</td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">maxThreads</td>
+ <td valign="top">The maximum number of allowable threads when executing
+ in parallel.</td>
+ <td align="center" valign="top">No. Defaults to 5.</td>
+ </tr>
+ <tr>
+ <td valign="top">trim</td>
+ <td valign="top">If <code>true</code>, any leading or trailing
+ whitespace will be removed from the list item before it is passed
+ to the requested target
+ </td>
+ <td align="center" valign="top">No. Defaults to false.</td>
+ </tr>
+ </table>
+
+ <h2>Parameters specified as nested elements</h2>
+
+ <a name="path"><h3>path</h3></a>
+
+ <p><a href="http://ant.apache.org/manual/using.html#path">Path</a>s
+ are used to select sets of files or directories to iterate over.</p>
+
+ <p>Using a path allows you to determine the order by which files
+ are considered by using
+ <a href="http://ant.apache.org/manual/CoreTypes/filelist.html">filelist</a>s
+ or explicit <code>pathelements</code>. You also can specify
+ whether you want to iterate over files or directories by chosing
+ either filesets or
+ <a href="http://ant.apache.org/manual/CoreTypes/dirset.html">dirset</a>s.</p>
+
+ <a name="fileset"><h3>fileset</h3></a>
+
+ <p><a href="http://ant.apache.org/manual/CoreTypes/fileset.html">FileSet</a>s
+ are used to select sets of files to iterate over. <strong>This
+ element is deprecated, use <a href="#path">nested path elements</a>
+ instead.</strong></p>
+
+ <h3>param</h3>
+
+ <p>Specifies the properties to set before running the specified
+ target. See <a href="http://ant.apache.org/manual/CoreTasks/property.html">property</a>
+ for usage guidelines.</p>
+
+ <h3><a name="reference">reference</a></h3>
+
+ <p>Used to chose references that shall be copied into the new
+ project, optionally changing their id.</p>
+
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">refid</td>
+ <td valign="top">The id of the reference in the calling project.</td>
+ <td valign="top" align="center">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">torefid</td>
+ <td valign="top">The id of the reference in the called project.</td>
+ <td valign="top" align="center">No, defaults to the value of
+ refid.</td>
+ </tr>
+ </table>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/forget.html b/docs/manual/tasks/forget.html
new file mode 100644
index 0000000..59b5d46
--- /dev/null
+++ b/docs/manual/tasks/forget.html
@@ -0,0 +1,62 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Forget</title>
+ </head>
+
+ <body>
+ <h1>Forget</h1>
+
+ <p>The Forget task will execute a set of tasks sequentially as a background
+ thread. Once the thread is started, control is returned to the calling
+ target. This is useful in being able to kick off a background server process,
+ such as a webserver. This allows you to not have to use the <code>parallel</code>
+ task to start server processes.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">daemon</td>
+ <td valign="top">Should the created thread be a daemon thread. That is,
+ should the ANT program be allowed to exit if the thread is still
+ running.</td>
+ <td align="center" valign="top">No. Defaults to true.</td>
+ </tr>
+ </table>
+
+
+ <h2>Example</h2>
+
+
+ The following code
+
+ <pre>
+ <code>
+ &lt;forget&gt;
+ &lt;exec executeable="${env.CATALINA_HOME}/bin/catalina.bat}"&gt;
+ &lt;arg line="start -security" /&gt;
+ &lt;/exec&gt;
+ &lt;/forget&gt;
+
+ &lt;waitfor maxwait="1" maxwaitunit="minute"
+ checkevery="100" checkeveryunit="millisecond"&gt;
+ &lt;http url="http://localhost:8080" /&gt;
+ &lt;/waitfor&gt;
+
+ </code>
+ </pre>
+
+ Would start the Tomcat webserver as a background process, then waiting
+ for the server to become available.
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/if.html b/docs/manual/tasks/if.html
new file mode 100644
index 0000000..e080d22
--- /dev/null
+++ b/docs/manual/tasks/if.html
@@ -0,0 +1,94 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: If</title>
+ </head>
+
+ <body>
+ <h1>If</h1>
+
+ <p>Perform some tasks based on whether a given condition holds
+ true or not.</p>
+
+ <p>This task is heavily based on the Condition framework that can
+ be found in Ant 1.4 and later, therefore it cannot be used
+ inconjunction with versions of Ant prior to 1.4. Due to numeruos
+ bugs in Ant 1.4(.1) that affect this task, we recommend to use Ant
+ 1.5 or later.</p>
+
+ <h2>Parameters</h2>
+
+ <p>This task doesn't have any attributes, the condition to test is
+ specified by a nested element - see the documentation of your
+ <code>&lt;condition&gt;</code> task (see <a
+ href="http://ant.apache.org/manual/CoreTasks/condition.html">the
+ online documentation</a> for example) for a complete list of
+ nested elements.</p>
+
+ <p>Just like the <code>&lt;condition&gt;</code> task, only a
+ single condition can be specified - you combine them using
+ <code>&lt;and&gt;</code> or <code>&lt;or&gt;</code>
+ conditions.</p>
+
+ <p>In addition to the condition, you can specify three different
+ child elements, <code>&lt;elseif&gt;</code>, <code>&lt;then&gt;</code> and
+ <code>&lt;else&gt;</code>. All three subelements are optional.
+
+ Both <code>&lt;then&gt;</code> and <code>&lt;else&gt;</code> must not be
+ used more than once inside the if task. Both are
+ containers for Ant tasks, just like Ant's
+ <code>&lt;parallel&gt;</code> and <code>&lt;sequential&gt;</code>
+ tasks - in fact they are implemented using the same class as Ant's
+ <code>&lt;sequential&gt;</code> task.</p>
+
+ The <code>&lt;elseif&gt;</code> behaves exactly like an <code>&lt;if&gt;</code>
+ except that it cannot contain the <code>&lt;else&gt;</code> element
+ inside of it. You may specify as may of these as you like, and the
+ order they are specified is the order they are evaluated in. If the
+ condition on the <code>&lt;if&gt;</code> is false, then the first
+ <code>&lt;elseif&gt;</code> who's conditional evaluates to true
+ will be executed. The <code>&lt;else&gt;</code> will be executed
+ only if the <code>&lt;if&gt;</code> and all <code>&lt;elseif&gt;</code>
+ conditions are false.
+
+ <h2>Example</h2>
+
+<pre><code>
+&lt;if&gt;
+ &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;bar&quot; /&gt;
+ &lt;then&gt;
+ &lt;echo message=&quot;The value of property foo is bar&quot; /&gt;
+ &lt;/then&gt;
+ &lt;else&gt;
+ &lt;echo message=&quot;The value of property foo is not bar&quot; /&gt;
+ &lt;/else&gt;
+&lt;/if&gt;
+</code></pre>
+
+<pre><code>
+&lt;if&gt;
+ &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;bar&quot; /&gt;
+ &lt;then&gt;
+ &lt;echo message=&quot;The value of property foo is 'bar'&quot; /&gt;
+ &lt;/then&gt;
+
+ &lt;elseif&gt;
+ &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;foo&quot; /&gt;
+ &lt;then&gt;
+ &lt;echo message=&quot;The value of property foo is 'foo'&quot; /&gt;
+ &lt;/then&gt;
+ &lt;/elseif&gt;
+
+
+ &lt;else&gt;
+ &lt;echo message=&quot;The value of property foo is not 'foo' or 'bar'&quot; /&gt;
+ &lt;/else&gt;
+&lt;/if&gt;
+</code></pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/index.html b/docs/manual/tasks/index.html
new file mode 100644
index 0000000..8da6784
--- /dev/null
+++ b/docs/manual/tasks/index.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-Contrib Tasks</title>
+ </head>
+
+ <frameset cols="25%,75%">
+ <frame src="toc.html" name="navFrame">
+ <frame src="foreach.html" name="mainFrame">
+ </frameset>
+ <noframes>
+ <h2>Ant-Contrib Tasks</h2>
+
+ <a href="toc.html">Task List</a>
+ </noframes>
+</html>
diff --git a/docs/manual/tasks/inifile.html b/docs/manual/tasks/inifile.html
new file mode 100644
index 0000000..d5722a9
--- /dev/null
+++ b/docs/manual/tasks/inifile.html
@@ -0,0 +1,110 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: IniFile</title>
+ </head>
+
+ <body>
+ <h1>IniFile</h1>
+
+ <p>Build and Edit Windows .ini files. Only the simple edits,
+ <code>remove</code> and <code>set</code> are allowed. Set
+ has limited computation capability which is described later.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">source</td>
+ <td valign="top">The name source .ini file to read in.</td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+ <tr>
+ <td valign="top">dest</td>
+ <td valign="top">The name destination .ini file to write.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </table>
+
+
+ <h2>Parameters specified as nested elements</h2>
+
+ <code>remove</code>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">section</td>
+ <td valign="top">The name of the section</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name property.</td>
+ <td align="center" valign="top">No. If not supplied, the entire
+ section will be removed</td>
+ </tr>
+ </table>
+
+ <code>set</code>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">section</td>
+ <td valign="top">The name of the section</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name property.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">value</td>
+ <td valign="top">The value to set the property to.</td>
+ <td align="center" valign="top">No, if
+ <code>operation</code> is specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">operation</td>
+ <td valign="top">The operation to perform on the existing value.
+ Possible values are "+" and "-", which add and subtract 1,
+ respectively from the existing value. If the value doesn't
+ already exist, the set is not performed.</td>
+ <td align="center" valign="top">No, if <code>value</code>
+ is specified.</td>
+ </tr>
+ </table>
+
+ <h2>Example</h2>
+
+
+
+<pre><code>
+
+&lt;inifile source="myprog.ini" dest="myprog.new.ini"&gt;
+ &lt;set section="Section1" property="release-date" value="${todays.date}" />
+ &lt;set section="Section1" property="build-number" operation="+" />
+ &lt;remove section="Section2" property="useless" />
+ &lt;remove section="OutdatedSection" />
+&lt;/inifile&gt;
+</code></pre>
+
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/limit_task.html b/docs/manual/tasks/limit_task.html
new file mode 100644
index 0000000..fb8f305
--- /dev/null
+++ b/docs/manual/tasks/limit_task.html
@@ -0,0 +1,280 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Chapter&nbsp;10.&nbsp;Limit</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch09.html" title="Chapter&nbsp;9.&nbsp;Stopwatch">
+<link rel="next" href="bk03ch11.html" title="Chapter&nbsp;11.&nbsp;Math">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="Limit">
+</a>
+Limit</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The Limit task is a task container (that is, it holds other tasks) and sets a time limit on how long the nested tasks are allowed to run. This is useful for unit tests that go awry, hung socket connections, or other potentially long running tasks that need to be shut off without stopping the build.
+</p>
+
+<p>
+
+<div class="table">
+<a name="N1096A">
+</a>
+<p class="title">
+<b>
+Table&nbsp;10.1.&nbsp;Limit Task Attributes</b>
+</p>
+<table summary="Limit Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+maxwait</td>
+<td>
+How long to wait for nested tasks to finish.</td>
+<td>
+180 seconds (3 minutes)</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+maxwaitunit</td>
+<td>
+The unit for maxwait. Valid values are "millisecond", "second", "minute", "hour", "day", "week".</td>
+<td>
+seconds</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+failonerror</td>
+<td>
+Should the build fail if the time limit has been exceeded?</td>
+<td>
+false</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+property</td>
+<td>
+The name of a property to set if the max wait time is exceeded.</td>
+<td>
+none</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+value</td>
+<td>
+The value to set for the property if the max wait time is exceeded.</td>
+<td>
+true</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+milliseconds</td>
+<td>
+How long to wait in milliseconds.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+seconds</td>
+<td>
+How long to wait in seconds.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+minutes</td>
+<td>
+How long to wait in minutes.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+hours</td>
+<td>
+How long to wait in hours.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+days</td>
+<td>
+How long to wait in days.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+weeks</td>
+<td>
+How long to wait in weeks.</td>
+<td>
+3 minutes</td>
+<td>
+No</td>
+</tr>
+
+
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+Examples:
+</p>
+<p>
+
+Neither the echo nor the fail will happen in this example. The build will continue once the time has expired.
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;limit maxwait="3"&gt;
+ &lt;sleep seconds="10"/&gt;
+ &lt;echo&gt;This won't happen...&lt;/echo&gt;
+ &lt;fail&gt;This won't happen either...&lt;/fail&gt;
+&lt;/limit&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+This is identical to the above example, but uses the convenience "seconds" attribute:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;limit seconds="3"&gt;
+ &lt;sleep seconds="10"/&gt;
+ &lt;echo&gt;This won't happen...&lt;/echo&gt;
+ &lt;fail&gt;This won't happen either...&lt;/fail&gt;
+&lt;/limit&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+Neither the echo nor the fail will happen in this example. The build will not continue once the time has expired.
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;limit maxwait="3" failonerror="true"&gt;
+ &lt;sleep seconds="10"/&gt;
+ &lt;echo&gt;This won't happen...&lt;/echo&gt;
+ &lt;fail&gt;This won't happen either...&lt;/fail&gt;
+&lt;/limit&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+The limit will be reached and a property will be set indicating so.
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;limit minutes="3" property="limit_reached"&gt;
+ &lt;sleep minutes="10"/&gt;
+ &lt;echo&gt;This won't happen...&lt;/echo&gt;
+ &lt;fail&gt;This won't happen either...&lt;/fail&gt;
+&lt;/limit&gt;
+&lt;echo&gt;limit_reached = ${limit_reached)&lt;/echo&gt;
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/math_task.html b/docs/manual/tasks/math_task.html
new file mode 100644
index 0000000..bac6e04
--- /dev/null
+++ b/docs/manual/tasks/math_task.html
@@ -0,0 +1,405 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Math</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch10.html" title="Chapter&nbsp;10.&nbsp;Limit">
+<link rel="next" href="bk03ch12.html" title="Chapter&nbsp;12.&nbsp;HTTP Post">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="math">
+</a>
+Math</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The Math task provides support for all the basic mathematical operations
+provided by the java.lang.Math and java.lang.StrictMath classed. It supports int, long, float and double data types. Nesting of operations is supported to allow computation of formulas like (6 + (7.25 * 3.9))/(2 * 3 * 3) or calculating the area of a circle given a radius (I'm sure this comes up often in builds controlled by Ant!).
+</p>
+<p>
+
+In addition to the operations provided by the java.lang.Math and java.lang.StrictMath classes, the Math task provides several additional operations: "add", "subtract", "multiply", "divide", and "mod", which duplicate the basic Java mathematical operations "+", "-", "*", "/", and "%", respectively. In fact, either notation can be used, that is, the operation can be set to "add" or "+", depending only on which you feel is more convenient.
+</p>
+
+<p>
+
+<div class="table">
+<a name="N109AE">
+</a>
+<p class="title">
+<b>
+Table&nbsp;11.1.&nbsp;Math Task Attributes</b>
+</p>
+<table summary="Math Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+result</td>
+<td>
+The name of the property to hold the result of the operation.</td>
+<td>
+None</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+datatype</td>
+<td>
+Sets the datatype of the calculation. Allowed values are
+"int", "long", "float", or "double". Optional, if
+used, will be applied to all numbers in this math operation.</td>
+<td>
+double</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+strict</td>
+<td>
+If true, use the methods in the java.lang.StrictMath class.</td>
+<td>
+false</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+operation</td>
+<td>
+If used, any nested Ops will be ignored. This is for convenience for simple calculations.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+operand1</td>
+<td>
+A number to use with the operation specified in the 'operation' attribute.</td>
+<td>
+None</td>
+<td>
+Depends on the specific operation.</td>
+</tr>
+<tr>
+<td>
+operand2</td>
+<td>
+A number to use with the operation specified in the 'operation' attribute.</td>
+<td>
+None</td>
+<td>
+Depends on the specific operation.</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+The 'result' property is reusable.
+</p>
+
+
+The Math task supports nested "Op" elements. An Op element represents single mathematical operation, such as "min" or "add".
+As an alternate, if using Ant 1.5+, you can specify the operation in the tag name itself. However, you must use the text
+name (+,-,/,*,% are not permitted as tag names)
+
+<code><pre>
+ &lt;radians&gt;
+ &lt;num value="90" /&gt;
+ &lt;/radians&gt;
+</pre></code>
+
+instead of
+
+<code><pre>
+ &lt;op op="radians"&gt;
+ &lt;num value="90" /&gt;
+ &lt;/op&gt;
+</pre></code>
+
+
+<p>
+
+<div class="table">
+<a name="N109FB">
+</a>
+<p class="title">
+<b>
+Table&nbsp;11.2.&nbsp;Op Attributes</b>
+</p>
+<table summary="Op Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+op</td>
+<td>
+Set the name of this operation. Allowed values are
+one of the method names from java.lang.Math or java.lang.StrictMath, or one of
+"add", "subtract", "multiply", "divide", or "mod" (or "+", "-", "*", "/", or "%",
+respectively). "toRadians" and "toDegrees" can be represented by "radians" and
+"degrees", respectively, as a shorthand</td>
+<td>
+None</td>
+<td>
+Yes, if not specified in the tag name.</td>
+</tr>
+<tr>
+<td>
+datatype</td>
+<td>
+Sets the datatype of this calculation. Allowed values are
+"int", "long", "float", or "double". Optional, default
+is "double". If the parent Math task has a datatype set, this value will be ignored and the datatype specifed in the task will be used.</td>
+<td>
+"int"</td>
+<td>
+No</td>
+</tr>
+
+<tr>
+<td>
+arg1, arg2, arg3, arg4, arg5/td>
+<td>
+The arguments for this operation. This is a shorthand to avoid having to use nested
+elements when performing a simple calculation.
+</td>
+<td>
+None</td>
+<td>
+No. However, these attributes are mutually exclusive with the <op> and <num> subelements.</td>
+</tr>
+
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+The Op element supports nested "Op" elements and nested "Num" elements. A Num represents a number.
+When an Op is nested in another Op, the result of the Op is treated as a Num. The nested elements
+can be any combination of Op (short form included as mentioned above) or Num as appropriate for the
+formula being calculated. Most of the
+operations provided by java.lang.Math and java.lang.StrictMath operate on one or two numbers.
+The "+", "-", "*", "/", and "%" operations can task any number of nested numbers.
+</p>
+<p>
+
+<div class="table">
+<a name="N10A23">
+</a>
+<p class="title">
+<b>
+Table&nbsp;11.3.&nbsp;Num Attributes</b>
+</p>
+<table summary="Num Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+value</td>
+<td>
+Set the value for this number. Must be able to parse to the datatype set by the parent element or the default datatype set by the task. Two special numbers, pi and e, can be represented by PI and E respectively. ("PI" is the ratio of the diameter of a circle to its radius, "E" is Euler's e, the base for natural logrithms.)</td>
+<td>
+None</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+datatype</td>
+<td>
+Sets the datatype of this number. Allowed values are
+"int", "long", "float", or "double". Optional, default
+is "double". If the parent Math task has a datatype set, this value will be ignored and the datatype specifed in the task will be used.</td>
+<td>
+double</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+Some examples:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;var name="op1" value="12"/&gt;
+ &lt;var name="op2" value="6"/&gt;
+ &lt;var name="op" value="+"/&gt;
+
+ &lt;!-- demo plus --&gt;
+ &lt;math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="18"/&gt;
+
+ &lt;!-- demo reusing result --&gt;
+ &lt;math result="result" operand1="${result}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="24"/&gt;
+
+ &lt;!-- demo minus --&gt;
+ &lt;var name="op" value="-"/&gt;
+ &lt;math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="6"/&gt;
+
+ &lt;!-- demo multiply --&gt;
+ &lt;var name="op" value="*"/&gt;
+ &lt;math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="72"/&gt;
+
+ &lt;!-- demo divide --&gt;
+ &lt;var name="op" value="/"/&gt;
+ &lt;math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="2"/&gt;
+
+ &lt;!-- demo modulo --&gt;
+ &lt;var name="op" value="%"/&gt;
+ &lt;math result="result" operand1="${op1}" operation="${op}" operand2="${op2}" datatype="int"/&gt;
+ &lt;echo&gt;${op1} ${op} ${op2} = ${result}&lt;/echo&gt;
+ &lt;assert name="result" value="0"/&gt;
+
+ &lt;!-- demo calculating the area of a circle --&gt;
+ &lt;!-- first, calculate the radius --&gt;
+ &lt;math result="radius"&gt; &lt;!-- defaults to double datatype --&gt;
+ &lt;op type="*"&gt;
+ &lt;num value="1"/&gt;
+ &lt;num value="2"/&gt;
+ &lt;num value="3"/&gt;
+ &lt;num value="4"/&gt;
+ &lt;num value="5"/&gt;
+ &lt;/op&gt;
+ &lt;/math&gt;
+ &lt;echo&gt; 1 * 2 * 3 * 4 * 5 = ${radius}&lt;/echo&gt;
+
+ &lt;!-- now calculate the area --&gt;
+ &lt;math result="area" precision="float"&gt;
+ &lt;op type="*"&gt;
+ &lt;num value="PI"/&gt;
+ &lt;op type="pow"&gt;
+ &lt;num value="${radius}"/&gt;
+ &lt;num value="2"/&gt;
+ &lt;/op&gt;
+ &lt;/op&gt;
+ &lt;/math&gt;
+ &lt;echo&gt;area = PI * radius ^ 2 = ${area}&lt;/echo&gt;
+
+ &lt;!-- demo calculating a random number between 0 and 100 --&gt;
+ &lt;math result="result"&gt;
+ &lt;op op="rint"&gt;
+ &lt;op op="*"&gt;
+ &lt;num value="100"/&gt;
+ &lt;op op="random"/&gt;
+ &lt;/op&gt;
+ &lt;/op&gt;
+ &lt;/math&gt;
+ &lt;echo&gt;a random number between 0 and 100: ${result}&lt;/echo&gt;
+
+ &lt;!-- demo another multiplication --&gt;
+ &lt;math result="result" operation="multiply" operand1="17" operand2="13"/&gt;
+ &lt;echo&gt;${result}&lt;/echo&gt;
+
+ &lt;!-- demo shorthand notation for calculating sin of an angle, which is degrees --&gt;
+ &lt;math result="sin"&gt;
+ &lt;sin&gt;
+ &lt;radians arg1="${angle_in_degrees}" /&gt;
+ &lt;/sin&gt;
+ &lt;/math&gt;
+ &lt;echo&gt;${sin}&lt;/echo&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/more_conditions.html b/docs/manual/tasks/more_conditions.html
new file mode 100644
index 0000000..5c64602
--- /dev/null
+++ b/docs/manual/tasks/more_conditions.html
@@ -0,0 +1,461 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+More Conditions</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03ch05.html" title="Chapter&nbsp;5.&nbsp;If Task">
+<link rel="previous" href="bk03ch05.html" title="Chapter&nbsp;5.&nbsp;If Task">
+<link rel="next" href="bk03ch06.html" title="Chapter&nbsp;6.&nbsp;SwitchTask">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="section" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title" style="clear: both">
+<a name="conditionals">
+</a>
+More Conditions</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+These conditions are suitable for use in the &lt;bool&gt; element. Unfortunately, they cannot be used in the &lt;condition&gt; task, although all conditions for the &lt;condition&gt; task can be used with the &lt;bool&gt; and the &lt;bool&gt; can be used anywhere that &lt;condition&gt; can be used.
+</p>
+<h4>
+<a name="N10708">
+</a>
+IfPropertyTrue</h4>
+<p>
+
+Given a property name, tests whether the value for that property equals "true" (or "yes" or "on").
+</p>
+<p>
+
+<div class="table">
+<a name="N1070F">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.2.&nbsp;IfPropertyTrue Attributes</b>
+</p>
+<table summary="IfPropertyTrue Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+property</td>
+<td>
+The name of a property to test the value of.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;ispropertytrue property="myprop"/&gt;
+&lt;ispropertytrue property="${someprop}"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<h4>
+<a name="N1072C">
+</a>
+IfPropertyFalse</h4>
+<p>
+
+Given a property name, tests whether the value for that property equals "false" (or "no" or "off").
+</p>
+<p>
+
+<div class="table">
+<a name="N10733">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.3.&nbsp;IfPropertyFalse Attributes</b>
+</p>
+<table summary="IfPropertyFalse Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+property</td>
+<td>
+The name of a property to test the value of.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;ispropertyfalse property="myprop"/&gt;
+&lt;ispropertyfalse property="${someprop}"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<h4>
+<a name="N10750">
+</a>
+StartsWith</h4>
+<p>
+
+Given a property name, tests whether the value for that property starts with a specified string.
+</p>
+<p>
+
+<div class="table">
+<a name="N10757">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.4.&nbsp;StartsWith Attributes</b>
+</p>
+<table summary="StartsWith Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+string</td>
+<td>
+The string to test.</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+with</td>
+<td>
+Check if 'string' starts with this value.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;startswith string="abcdefg" with="abc"/&gt;
+&lt;startswith string="${myprop}" with="foo"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<h4>
+<a name="N1077B">
+</a>
+EndsWith</h4>
+<p>
+
+Given a property name, tests whether the value for that ends with with a specified string.
+</p>
+<p>
+
+<div class="table">
+<a name="N10782">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.5.&nbsp;EndsWith Attributes</b>
+</p>
+<table summary="EndsWith Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+string</td>
+<td>
+The string to test.</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+with</td>
+<td>
+Check if 'string' ends with this value.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;endswith string="abcdefg" with="efg"/&gt;
+&lt;endswith string="${myprop}" with="bar"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<h4>
+<a name="N107A6">
+</a>
+IsGreaterThan</h4>
+<p>
+
+Tests whether the first argument is greater than the second argument. Will
+automatically treat the arguments as numbers if both arguments consists of only the characters 0 through 9 and optionally a decimal point. Otherwise, a String
+comparison is used.
+</p>
+<p>
+
+<div class="table">
+<a name="N107AD">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.6.&nbsp;IsGreaterThan Attributes</b>
+</p>
+<table summary="IsGreaterThan Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+arg1</td>
+<td>
+The first argument.</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+arg2</td>
+<td>
+The second argument.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;!-- evaluates to true --&gt;
+&lt;isgreaterthan arg1="6.02" arg2="4"/&gt;
+
+&lt;!-- evaluates to false --&gt;
+&lt;isgreaterthan arg1="bar" arg2="foo"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<h4>
+<a name="N107D1">
+</a>
+IsLessThan</h4>
+<p>
+
+Tests whether the first argument is less than the second argument. Will
+automatically treat the arguments as numbers if both arguments consists of only the characters 0 through 9 and optionally a decimal point. Otherwise, a String
+comparison is used.
+</p>
+<p>
+
+<div class="table">
+<a name="N107D8">
+</a>
+<p class="title">
+<b>
+Table&nbsp;5.7.&nbsp;IsLessThan Attributes</b>
+</p>
+<table summary="IsLessThan Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+arg1</td>
+<td>
+The first argument.</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+arg2</td>
+<td>
+The second argument.</td>
+<td>
+Yes</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;!-- evaluates to false --&gt;
+&lt;islessthan arg1="6.02" arg2="4"/&gt;
+
+&lt;!-- evaluates to true --&gt;
+&lt;islessthan arg1="bar" arg2="foo"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/osfamily.html b/docs/manual/tasks/osfamily.html
new file mode 100644
index 0000000..e56bdaf
--- /dev/null
+++ b/docs/manual/tasks/osfamily.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Osfamily</title>
+ </head>
+
+ <body>
+ <h1>Osfamily</h1>
+
+ <p>Task definition for the <code>OsFamily</code> task. This task
+ sets the property indicated in the &quot;property&quot; attribute
+ with the string representing the operating system family.
+ Possible values include &quot;unix&quot;, &quot;dos&quot;,
+ &quot;mac&quot;, &quot;os/2&quot;, &quot;os/400&quot;,
+ &quot;z/os&quot;, &quot;tandem&quot; and &quot;windows&quot;.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property to set with the OS
+ family name.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </table>
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/outofdate.html b/docs/manual/tasks/outofdate.html
new file mode 100644
index 0000000..adffa19
--- /dev/null
+++ b/docs/manual/tasks/outofdate.html
@@ -0,0 +1,326 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
+ <TITLE>Ant-contrib Tasks: OutOfDate</TITLE>
+ <META NAME="GENERATOR" CONTENT="OpenOffice.org 644 (Linux)">
+ <META NAME="CREATED" CONTENT="20030314;12023500">
+ <META NAME="CHANGED" CONTENT="20030319;15211400">
+</HEAD>
+<BODY LANG="en-US" DIR="LTR">
+<H1>OutOfDate</H1>
+<P>Task definition for the <CODE>outofdate</CODE> task. This is an
+extension of uptodate which allows multible targets and contains an
+embedded &lt;parallel&gt; or &lt;sequential&gt; element. If any of
+the target file's dates are earlier than any of the source file's
+dates, then the specified &lt;parallel&gt; or &lt;sequential&gt;
+block is executed. The task may also contain mappers to map source
+files to corresponding target files.
+</P>
+<H2>Parameters</H2>
+<TABLE WIDTH=100% BORDER=1 CELLPADDING=2 CELLSPACING=0>
+ <COL WIDTH=0>
+ <COL WIDTH=0>
+ <COL WIDTH=0>
+ <TR>
+ <TH>
+ <P>Attribute</P>
+ </TH>
+ <TH>
+ <P>Description</P>
+ </TH>
+ <TH>
+ <P>Required</P>
+ </TH>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>property</P>
+ </TD>
+ <TD>
+ <P>The name of the property to set to the contents of the <CODE>value</CODE>
+ parameter if any of the target files are out of date</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>value</P>
+ </TD>
+ <TD>
+ <P>The value to set the property specified by the parameter
+ <CODE>property</CODE> to, if any of the target files are out of
+ date</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No, defaults to &quot;true&quot;</P>
+ </TD>
+ </TR>
+ <tr>
+ <td valign="top">force</td>
+ <td valign="top">
+ Force outofdate ("true"/"false"). Default is "false".
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">verbose</td>
+ <td valign="top">
+ Set vebose logging level for this task ("true"/"false").
+ Default is "false".
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>outputsources</P>
+ </TD>
+ <TD>
+ <P>The name of a property to set containing the sources that are
+ newer that their corresponding targets.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>outputtargets</P>
+ </TD>
+ <TD>
+ <P>The name of a property to set containing the targets that are
+ outofDate with respect to their corresponding sources.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>alltargets</P>
+ </TD>
+ <TD>
+ <P>The name of a property to set containing all the targets. This
+ is usefull for debugging mapper nested elements.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>separator</P>
+ </TD>
+ <TD>
+ <P>The separator used to separate the files in the properties
+ above. If a filename contains the separator, double quotes will be
+ placed aroudnd the filename.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No, defaults to “ “</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>outputsourcespath</P>
+ </TD>
+ <TD>
+ <P>The id of a path to create containing the source files that are
+ outofdate.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>outputtargetspath</P>
+ </TD>
+ <TD>
+ <P>The id of a path to create containing the target files that
+ need to be updated.</P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD>
+ <P>alltargetspath</P>
+ </TD>
+ <TD>
+ <P>The id of a path to create containing all the target files.
+ </P>
+ </TD>
+ <TD>
+ <P ALIGN=LEFT>No</P>
+ </TD>
+ </TR>
+</TABLE>
+<H2>Attributes specified as nested elements</H2>
+
+<P><B>sourcefiles</B> - The list of files which are source files.
+This element is required.
+<BR><BR><B>targetfiles</B> - The list of
+files which are target files.
+</P>
+<P>Both of these nested elements are <A HREF="http://ant.apache.org/manual/using.html#path">Path</A>
+elements which are are used to select sets or lists of files or
+directories</P>
+ <p>The <i>sourcefiles</i> may contain no files. In this case, outofdate will
+ check the existance of the <i>targetfiles</i>.</p>
+<P><B>mapper –</B> This is used to map source files to target
+files.</P>
+As well as the regular attributes for mapper, there is a extra attribute to specify
+ the relative directory of the sources.<p>
+ <table cellspacing="0" cellpadding="2" border="1">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">dir</td>
+ <td valign="top">
+ The directory to the sources are relative to for the mapper.
+ Default is ${base.dir}.
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ </table>
+
+<P>There may be a number of mapper nested elements.
+<P><B>deletetargets –</B> This is used to delete targets if the
+corresponding sources are outofdate.
+</P>
+ <table cellspacing="0" cellpadding="2" border="1">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">all</td>
+ <td valign="top">
+ Whether to delete all the targets ("true"/"false"). Defaults to
+ "false".
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">quiet</td>
+ <td valign="top">
+ Do not display diagnostic messages when deleting targets
+ ("true"/ "false"). Defaults to false.
+ When set to "true", if a file or directory cannot be deleted,
+ no error is reported. This setting emulates the -f option to
+ the Unix rm command. Default is "false".
+ Setting this to "true" implies setting failonerror to "false"
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ <tr>
+ <td valign="top">failonerror</td>
+ <td valign="top">
+ Controls whether an error (such as a failure to delete a file)
+ stops the build or is merely reported to the screen.
+ Only relevant if quiet is &quot;false&quot;.
+ Default is &quot;true&quot;.
+ Controls whether a failure to delete a target stops
+ the build or is merely reported to the screen.
+ </td>
+ <td valign="top">No</td>
+ </tr>
+ </table>
+
+</P>
+<H2>Examples</H2>
+<P>The following example creates the file ${jrun.file} if is older
+that build.xml, or any file in ${lib.dir}.</P>
+<PRE> &lt;outofdate&gt;
+ &lt;sourcefiles&gt;
+ &lt;pathelement path="build.xml"/&gt;
+ &lt;fileset dir="${lib.dir}"/&gt;
+ &lt;/sourcefiles&gt;
+ &lt;targetfiles path="${jrun.file}"/&gt;
+ &lt;sequential&gt;
+ &lt;mkdir dir=&quot;${build.bin.dir}&quot;/&gt;
+ &lt;echo file=&quot;${jrun.file}&quot; message=&quot;java -cp ${jrun.path} $*&quot;/&gt;
+ &lt;chmod file=&quot;${jrun.file}&quot; perm=&quot;ugo+rx&quot;/&gt;
+ &lt;/sequential&gt;
+ &lt;/outofdate&gt; </PRE><P>
+The following example check the generated files, MODULE.IDS,
+acme_agent_mib.h, acme_agent_mib.cpp are older that miblist.txt, or
+any file in ${mib.src}, and if so an embedded shellScript is invoked
+to update the files.</P>
+<PRE> &lt;outofdate&gt;
+ &lt;sourcefiles&gt;
+ &lt;pathelement path=&quot;${agent.src}/miblist.txt&quot;/&gt;
+ &lt;fileset dir=&quot;${mib.src}&quot;/&gt;
+ &lt;/sourcefiles&gt;
+ &lt;targetfiles&gt;
+ &lt;pathelement path=&quot;${rep}/MODULE.IDS&quot;/&gt;
+ &lt;pathelement path=&quot;${gen-agent}/acme_agent_mib.h&quot;/&gt;
+ &lt;pathelement path=&quot;${gen-agent}/acme_agent_mib.cpp&quot;/&gt;
+ &lt;/targetfiles&gt;
+ &lt;sequential&gt;
+ &lt;shellscript shell=&quot;bash&quot; dir=&quot;${agent.src}&quot;&gt;
+ classname=com.agentpp.agentgen.AgentGenConsole
+ h1=${gen-agent}/acme_agent_mib.x
+ ag() {
+ java -cp ${lib.dir}/agentgen.jar $classname ${rep} $@
+ }
+ ag initialize
+ ag load miblist.txt
+ ag generate ACME-AGENT-MIB h &gt; $h1
+ (head -16 $h1; echo &quot;using namespace Agentpp;&quot;;
+ tail +16 $h1) &gt; ${gen-agent}/acme_agent_mib.h
+ ag generate ACME-AGENT-MIB c &gt;\
+ ${gen-agent}/acme_agent_mib.cpp
+ &lt;/shellscript&gt;
+ &lt;/sequential&gt;
+ &lt;/outofdate&gt;</PRE><P>
+The following example sets the project <I>manual.outofdate</I> if any
+of the xml files are newer than index.html, or if any of the xml
+files are newer than their corresponding .html file. A path
+identified by <I>sources.path</I>, is created which contains the
+sources that fullfilled these conditions.</P>
+<PRE>
+ &lt;outofdate property="manual.outofdate" outputsourcespath="sources.path"&gt;
+ &lt;sourcefiles&gt;
+ &lt;fileset dir="${src.manual}" includes="**/*.xml"/&gt;
+ &lt;/sourcefiles&gt;
+ &lt;targetfiles path="${doc.manual}/index.html"/&gt;
+ &lt;mapper type="glob" dir="${src.manual}" from="*.xml" to="${doc.manual}/*.html"/&gt;
+ &lt;/outofdate&gt;
+</PRE>
+<P>
+The following assumes that there is a program called <I>gengrammer</I>
+that takes a grammer file as an input and generates a .h and a .c
+file in the current directory.</P>
+<PRE>
+ &lt;outofdate property="manual.outofdate"
+ outputsources="grammer.sources"&gt;
+ &lt;sourcefiles&gt;
+ &lt;fileset dir="${src.grammer}" includes="**/*.y"/&gt;
+ &lt;/sourcefiles&gt;
+ &lt;mapper type="glob" dir="${src.grammer}" from="*.y" to="${gen.grammer}/*.c"/&gt;
+ &lt;mapper type="glob" dir="${src.grammer}" from="*.y" to="${gen.grammer}/*.h"/&gt;
+ &lt;sequential&gt;
+ &lt;shellscript shell="bash"&gt;
+ cd ${gen.grammer}
+ for g in ${grammer.sources}
+ do
+ gengrammer $g
+ done
+ &lt;/shellscript&gt;
+ &lt;/sequential&gt;
+ &lt;/outofdate&gt;
+</PRE>
+<HR>
+<P ALIGN=CENTER>Copyright &copy; 2003 Ant-Contrib Project. All rights
+Reserved.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/docs/manual/tasks/pathtofileset.html b/docs/manual/tasks/pathtofileset.html
new file mode 100644
index 0000000..52e9cb7
--- /dev/null
+++ b/docs/manual/tasks/pathtofileset.html
@@ -0,0 +1,73 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Pathtofileset</title>
+ </head>
+
+ <body>
+ <h1>Pathtofileset</h1>
+
+ <p>Coverts a path to a fileset. This is usefull if you have
+ a path but need to use a fileset as input in a ant task.
+ </p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">dir</td>
+ <td valign="top">The root of the directory tree of this FileSet</td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">pathrefid</td>
+ <td valign="top">The reference to the path to convert from</td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ <tr>
+ <td valign="top">ignorenonrelative</td>
+ <td valign="top">This boolean controls what will happen if any of the
+ files in the path are not in the directory for the fileset. If this
+ is "true" the files are ignored, if this is "false" a build exception
+ is thrown. (Note: if files are not present no check is made).
+ </td>
+ <td align="center" valign="top">No, default is "false"</td>
+ </tr>
+ <tr>
+ <td valign="top">name</td>
+ <td valign="top">This is the identifier of the fileset to create. This
+ fileset will contain the files that are relative to the directory root.
+ Any files that are not present will not be placed in the set.
+ </td>
+ <td align="center" valign="top">Yes</td>
+ </tr>
+ </table>
+ </body>
+ <h2>Example</h2>
+ <pre>
+ &lt;outofdate outputsourcespath="modified.sources.path"&gt;
+ &lt;sourcefiles&gt;
+ &lt;fileset dir="a/b/c" includes="**/*.java"/&gt;
+ &lt;/sourcefiles&gt;
+ &lt;mapper dir="a/b/c" type="glob" from="*.java" to="output/*.xml"/&gt;
+ &lt;sequential&gt;
+ &lt;pathtofileset name="modified.sources.fileset"
+ pathrefid="modified.sources.path"
+ dir="a/b/c"/&gt;
+ &lt;copy todir="output"&gt;
+ &lt;fileset refid="modified.sources.fileset"/&gt;
+ &lt;mapper type="glob" from="*.java" to="*.xml"/&gt;
+ &lt;/copy&gt;
+ &lt;/sequential&gt;
+ &lt;/outofdate&gt;
+ </pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</html>
diff --git a/docs/manual/tasks/performance_monitor.html b/docs/manual/tasks/performance_monitor.html
new file mode 100644
index 0000000..3f92c80
--- /dev/null
+++ b/docs/manual/tasks/performance_monitor.html
@@ -0,0 +1,159 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Performance Monitoring</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch16.html" title="Chapter&nbsp;16.&nbsp;Call Task">
+<link rel="next" href="bk03ch18.html" title="Chapter&nbsp;18.&nbsp;Feedback">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="performance">
+</a>
+Performance Monitoring</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The "Performance Monitor" is
+a special Ant listener than can keep track of the amount of time that each target
+and task takes to execute. At the end of the build, these times will be sorted
+from fastest to slowest and displayed following the build output. This can be
+useful to pinpoint slow and/or inefficient spots in the build process and
+identify those areas that could benefit from optimization.
+</p>
+<p>
+
+The performance listener can be used by passing a parameter
+to the command line for Ant:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ ant -listener net.sf.antcontrib.perf.AntPerformanceListener target
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+Following is an example of the results from using the listener. The result format is projectname.targetname for targets and projectname.targetname.taskname for tasks. All times are shown to the nearest millisecond.
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+[danson@blackdog antelope]$ ant -listener net.sf.antcontrib.perf.AntPerformanceListener dist
+Buildfile: build.xml
+
+init:
+
+clean:
+ [delete] Deleting 170 files from /home/danson/apps/antelope/build
+
+compile:
+ [javac] Compiling 61 source files to /home/danson/apps/antelope/build
+
+all:
+
+-build_number:
+
+prep_files:
+ [delete] Deleting 3 files from /home/danson/apps/antelope/config
+ [copy] Copying 3 files to /home/danson/apps/antelope/config
+
+combined:
+ [echo] basedir = /home/danson/apps/antelope
+ [jar] Building jar: /home/danson/apps/antelope/Antelope_1.208.jar
+
+dist:
+ [delete] Deleting 4 files from /home/danson/apps/antelope/dist
+ [zip] Building zip: /home/danson/apps/antelope/dist/Antelope_1.208.zip
+ [echo] Created zip file.
+
+-zip_docs:
+ [zip] Building zip: /home/danson/apps/antelope/dist/Antelope_docs_1.208.zip
+ [echo] Zipped docs to Antelope_docs_1.208.zip.
+
+-zip_tasks:
+ [jar] Building jar: /tmp/Antelope_tasks_1.208.jar
+ [zip] Building zip: /home/danson/apps/antelope/dist/Antelope_tasks_1.208.zip
+ [delete] Deleting: /tmp/Antelope_tasks_1.208.jar
+ [echo] Zipped tasks to Antelope_tasks_1.208.zip.
+ [copy] Copying 1 file to /home/danson/apps/antelope/dist
+
+BUILD SUCCESSFUL
+Total time: 8 seconds
+
+-------------- Target Results -----------------------
+Antelope.all: 0.000 sec
+Antelope.init: 0.011 sec
+Antelope.-build_number: 0.014 sec
+Antelope.clean: 0.233 sec
+Antelope.-zip_tasks: 0.297 sec
+Antelope.prep_files: 0.311 sec
+Antelope.-zip_docs: 0.546 sec
+Antelope.combined: 1.290 sec
+Antelope.compile: 1.724 sec
+Antelope.dist: 2.162 sec
+
+-------------- Task Results -----------------------
+Antelope.init.mkdir: 0.000 sec
+Antelope.init.mkdir: 0.001 sec
+Antelope.dist.echo: 0.002 sec
+Antelope.prep_files.delete: 0.004 sec
+Antelope.combined.echo: 0.005 sec
+Antelope.dist.delete: 0.006 sec
+Antelope.-zip_tasks.echo: 0.007 sec
+Antelope.dist.copy: 0.011 sec
+Antelope.-build_number.buildnumber: 0.014 sec
+Antelope.compile.copy: 0.016 sec
+Antelope.prep_files.copy: 0.020 sec
+Antelope.prep_files.replace: 0.071 sec
+Antelope.-zip_tasks.zip: 0.122 sec
+Antelope.-zip_tasks.jar: 0.161 sec
+Antelope.prep_files.replace: 0.216 sec
+Antelope.clean.delete: 0.233 sec
+Antelope.dist.antcall: 0.421 sec
+Antelope.-zip_docs.zip: 0.540 sec
+Antelope.dist.antcall: 0.685 sec
+Antelope.dist.zip: 1.036 sec
+Antelope.combined.jar: 1.284 sec
+Antelope.compile.javac: 1.708 sec
+
+-------------- Totals -----------------------
+Start time: Thu, 5 Dec 2002 17:18:30
+Stop time: Thu, 5 Dec 2002 17:18:39
+Total time: 8.476 sec
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/post_task.html b/docs/manual/tasks/post_task.html
new file mode 100644
index 0000000..3be383c
--- /dev/null
+++ b/docs/manual/tasks/post_task.html
@@ -0,0 +1,366 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+HTTP Post</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch11.html" title="Chapter&nbsp;11.&nbsp;Math">
+<link rel="next" href="bk03ch13.html" title="Chapter&nbsp;13.&nbsp;SSH and SCP">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="post">
+</a>
+HTTP Post</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+The Post task is a companion to the standard Ant "Get" task. This task does a post and does not necessarily expect anything in return. Almost always, there will be some sort of returned data, this can be logged or written to a file if needed.
+</p>
+<p>
+Basically, an HTTP POST sends name/value pairs to a web server. A very common usage is for html forms for submitting data. A typical use of this task is to send data to a servlet for updating a web page with the status of a build.
+</p>
+<p>
+This task handles cookies correctly, which is useful for websites that set a session id to track logins or whatever. This means that if you do several posts in a row, cookies gathered from the first post will be returned with subsequent posts.
+</p>
+<p>
+The Post task has three ways of specifying the data to be posted. Nested "prop" elements can be used. A "prop" element represents a single name/value pair. The second way is to specify a property file as an attribute to the Post. All properties from the file will be sent as part of the Post data. The third way is to just type in some defined Ant properties. Is it allowed to use all three ways at once, that is, read some properties from a file, specify others via "prop" elements, and just type in some Ant properties.
+</p>
+<p>
+
+<div class="table">
+<a name="N10A61">
+</a>
+<p class="title">
+<b>
+Table&nbsp;12.1.&nbsp;Post Task Attributes</b>
+</p>
+<table summary="Post Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+to</td>
+<td>
+The URL of the remote server to send the post.</td>
+<td>
+None</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+encoding</td>
+<td>
+Character encoding for the name/value pairs.</td>
+<td>
+UTF-8</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+logfile</td>
+<td>
+The name of a file to write any response to. Ignored if wantresponse is set to false.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+property</td>
+<td>
+The name of a property to write any response to. Ignored if wantresponse is set to false.
+</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+append</td>
+<td>
+Should an existing log file be appended to or overwritten?</td>
+<td>
+True, append to an existing file.</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+file</td>
+<td>
+A file to read POST data from. All Ant properties contained in this file will be resolved (that is, ${} syntax will be expanded to their values) prior to sending the file contents.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+rawFile</td>
+<td>
+Should the file be trated as raw file instead of property-like file. True - send the content of the file directly to http-post, all properties set by 'property' are ignored!<br/>
+Has only impact when the property 'file' is specified.</td>
+<td>
+False, treat file as property-like</td>
+<td>
+No</td>
+</tr>
+<tr>
+<tr>
+<td>
+rawFileNoEncoding</td>
+<td>
+Don't encode the raw file prior to sending http post request.<br/>
+Has only impact when the property 'rawFile' is specified.</td>
+<td>
+False, http-encode the content of the file</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+maxwait</td>
+<td>
+The maximum amount of time in seconds to wait for the data to be sent or for a response from the remote server. Setting this to zero means wait forever.</td>
+<td>
+180 (3 minutes)</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+wantresponse</td>
+<td>
+Whether to wait for a response from the remote server or not. In many cases this can greatly improve the performance of the build script as the server response may be large and useless to the script. Use this with caution - while the response from the server may not be required for the client, the server may require that the client accept the response prior to processing the post data.</td>
+<td>
+true</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+failonerror</td>
+<td>
+Whether the build should fail if the post fails.</td>
+<td>
+false</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+Post supports nested "prop" elements. As an HTTP POST basically sends a list of names and values, the "prop" element represents one name/value pair. A Post may contain any number of "prop" elements.
+</p>
+<p>
+
+<div class="table">
+<a name="N10ABF">
+</a>
+<p class="title">
+<b>
+Table&nbsp;12.2.&nbsp;Prop Attributes</b>
+</p>
+<table summary="Prop Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+name</td>
+<td>
+The name of a property to post.</td>
+<td>
+None</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+value</td>
+<td>
+The value associated with the name.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+The "value" attribute is not strictly required. This provides a short-cut method in cases where the property data is an already-defined Ant property. Suppose the build file has this property defined:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="src.dir" value="/home/user/project/src"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+Then the following are equivalent:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;prop name="src.dir"/&gt;
+ &lt;prop name="src.dir" value="${src.dir}"/&gt;
+ &lt;prop name="src.dir" value="/home/user/project/src"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+Defined Ant properties can be entered directly into the post element. Again, suppose the build file has this property defined:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="src.dir" value="/home/user/project/src"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+Then the following are equivalent:
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ ${src.dir}
+ &lt;prop name="src.dir"/&gt;
+ &lt;prop name="src.dir" value="${src.dir}"/&gt;
+ &lt;prop name="src.dir" value="/home/user/project/src"/&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+I googled for the URL in the following example.
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="test.val" value="here's my test value"/&gt;
+ &lt;property name="test.val2" value="second test value"/&gt;
+ &lt;post to="http://wwwj.cs.unc.edu:8888/tang/servlet/tangGetPostServlet"
+ verbose="true"&gt;
+ &lt;prop name="prop1" value="val1 ${test.val}"/&gt;
+ &lt;prop name="prop2" value="val1 value 2"/&gt;
+ &lt;prop name="prop3" value="val got some spaces %funky ^$* chars"/&gt;
+ &lt;prop name="prop4" value="&amp;amp; do an ampersand like this &amp;amp;amp; or
+ Ant will whine"/&gt;
+ &lt;prop name="thanks" value="dude, thanks for the echo server!"/&gt;
+ &lt;prop name="test.val"/&gt;
+ ${test.val2}
+ &lt;/post&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/propertycopy.html b/docs/manual/tasks/propertycopy.html
new file mode 100644
index 0000000..e24358a
--- /dev/null
+++ b/docs/manual/tasks/propertycopy.html
@@ -0,0 +1,69 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Propertycopy</title>
+ </head>
+
+ <body>
+ <h1>Propertycopy</h1>
+
+ <p>Copies the value of a named property to another property. This
+ is useful when you need to plug in the value of another property
+ in order to get a property name and then want to get the value of
+ that property name.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">override</td>
+ <td valign="top">If the property is already set, should we change it's value.
+ Can be <code>true</code> or <code>false</code></td>
+ <td align="center" valign="top">No. Defaults to <code>false</code></td>
+ </tr>
+ <tr>
+ <td valign="top">name <i>Deprecated</i></td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">No. Use the <code>property</code> attribute
+ instead</td>
+ </tr>
+ <tr>
+ <td valign="top">from</td>
+ <td valign="top">The name of the property you wish to copy the
+ value from.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">silent</td>
+ <td valign="top">Do you want to suppress the error if the
+ &quot;from&quot; property does not exist, and just not set the
+ property &quot;name&quot;.</td>
+ <td align="center" valign="top">No, default is &quot;false&quot;.</td>
+ </tr>
+ </table>
+
+ <h2>Example</h2>
+<pre>
+&lt;property name=&quot;org&quot; value=&quot;MyOrg&quot; /&gt;
+&lt;property name=&quot;org.MyOrg.DisplayName&quot; value=&quot;My Organiziation&quot; /&gt;
+&lt;propertycopy name=&quot;displayName&quot; from=&quot;org.${org}.DisplayName&quot; /&gt;
+</pre>
+
+ <p>Sets <code>displayName</code> to &quot;My
+ Organiziation&quot;.</p>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/propertyregex.html b/docs/manual/tasks/propertyregex.html
new file mode 100644
index 0000000..33b855e
--- /dev/null
+++ b/docs/manual/tasks/propertyregex.html
@@ -0,0 +1,133 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: PropertyRegex</title>
+ </head>
+
+ <body>
+ <h1>PropertyRegex</h1>
+
+ <p>Performs regular expression operations on an input string, and sets
+ the results to a property. There are two different operations that
+ can be performed:
+ <ol type="1">
+ <li>Replacement - The matched regular expression is replaced with
+ a substitition pattern</li>
+ <li>Selection - Groupings within the regular expression are selected
+ via a selection expression.
+ </ol>
+ </p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">override</td>
+ <td valign="top">If the property is already set, should we change it's value.
+ Can be <code>true</code> or <code>false</code></td>
+ <td align="center" valign="top">No. Defaults to <code>false</code></td>
+ </tr>
+ <tr>
+ <td valign="top">input</td>
+ <td valign="top">The input string to be processed</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </tr>
+ <tr>
+ <td valign="top">regexp</td>
+ <td valign="top">The regular expression which is matched in
+ the input string.</td>
+ <td align="center" valign="top">Yes (can be specified in a
+ <code>&lt;regexp&gt;</code> subelement).
+ </td>
+ </tr>
+ <tr>
+ <td valign="top">select</td>
+ <td valign="top">A pattern which indicates what selection pattern you want
+ in the returned value. This uses the substitution pattern
+ syntax to indicate where to insert groupings created as a result
+ of the regular expression match.</td>
+ <td align="center" valign="top">Yes, unless a replace is specified</td>
+ </tr>
+ <tr>
+ <td valign="top">replace</td>
+ <td valign="top">A regular expression substitition pattern, which will be used
+ to replace the given regular expression in the input string.</td>
+ <td align="center" valign="top">Yes, unless a select is specified</td>
+ </tr>
+ <tr>
+ <td valign="top">casesensitive</td>
+ <td valign="top">Should the match be case sensitive</td>
+ <td align="center" valign="top">No. default is &quot;true&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">global</td>
+ <td valign="top">Should a replacement operation be performed on the entire
+ string, rather than just the first occurance</td>
+ <td align="center" valign="top">No. default is <code>false</code>.</td>
+ </tr>
+ <tr>
+ <td valign="top">defaultValue</td>
+ <td valign="top">The value to set the output property to, if the
+ input string does not match the specific regular expression.</td>
+ <td align="center" valign="top">No.</td>
+ </table>
+
+ <h2>Select expressions</h2>
+
+ Expressions are selected in a the same syntax as a regular expression
+ substitution pattern.
+
+ <ul type="o">
+ <li><code>\0</code> indicates the entire property name (default).
+ <li><code>\1</code> indicates the first grouping
+ <li><code>\2</code> indicates the second grouping
+ <li>etc...
+ </ul>
+
+ <h2>Replacement</h2>
+ It is important to note that when doing a "replace" operation,
+ if the input string does not match the regular expression, then
+ the property is not set. You can change this behavior by supplying
+ the "defaultValue" attribute. This attribute should contain the value
+ to set the property to in this case.
+
+ <h2>Example</h2>
+
+ <pre>
+ <code>
+ &lt;propertyregex property="pack.name"
+ input="package.ABC.name"
+ regexp="package\.([^\.]*)\.name"
+ select="\1"
+ casesensitive="false" /&gt;
+ </code>
+ yields <code>ABC</code>
+ </pre>
+
+ <pre>
+ <code>
+ &lt;propertyregex property="pack.name"
+ input="package.ABC.name"
+ regexp="(package)\.[^\.]*\.(name)"
+ replace="\1.DEF.\2"
+ casesensitive="false" /&gt;
+ </code>
+ yields <code>package.DEF.name</code>
+ </pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/propertyselector.html b/docs/manual/tasks/propertyselector.html
new file mode 100644
index 0000000..4e5102e
--- /dev/null
+++ b/docs/manual/tasks/propertyselector.html
@@ -0,0 +1,139 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: PropertySelector</title>
+ </head>
+
+ <body>
+ <h1>PropertySelector</h1>
+
+ <p>Selects property names that match a given regular expression and
+ returns them in a delimited list</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property you wish to set.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">override</td>
+ <td valign="top">If the property is already set, should we change it's value.
+ Can be <code>true</code> or <code>false</code></td>
+ <td align="center" valign="top">No. Defaults to <code>false</code></td>
+ </tr>
+ <tr>
+ <td valign="top">match</td>
+ <td valign="top">The regular expression which is used to select
+ property names for inclusion in the list. This follows
+ the standard regular expression syntax accepted by ant's
+ regular expression tasks.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">select</td>
+ <td valign="top">A pattern which indicates what selection pattern you want
+ in the returned list. This used the substitution pattern
+ syntax to indicate where to insert groupings created as a result
+ of the regular expression match.</td>
+ <td align="center" valign="top">No. default is &quot;\0&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">casesensitive</td>
+ <td valign="top">Should the match be case sensitive</td>
+ <td align="center" valign="top">No. default is &quot;true&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">delimiter</td>
+ <td valign="top">The delimiter used to seperate entries in the resulting
+ property</td>
+ <td align="center" valign="top">No. default is &quot;,&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">distinct</td>
+ <td valign="top">Should the returned entries be a distinct set (no duplicate
+ entries)</td>
+ <td align="center" valign="top">No. default is &quot;false&quot;.</td>
+ </tr>
+ </table>
+
+ <h2>Select expressions</h2>
+
+ Expressions are selected in a the same syntax as a regular expression
+ substitution pattern.
+
+ <ul type="o">
+ <li><code>\0</code> indicates the entire property name (default).
+ <li><code>\1</code> indicates the first grouping
+ <li><code>\2</code> indicates the second grouping
+ <li>etc...
+ </ul>
+
+ <h2>Example</h2>
+
+ The following code
+
+ <pre>
+ <code>
+ &lt;property name="package.ABC.name" value="abc pack name" /&gt;
+ &lt;property name="package.DEF.name" value="def pack name" /&gt;
+ &lt;property name="package.GHI.name" value="ghi pack name" /&gt;
+ &lt;property name="package.JKL.name" value="jkl pack name" /&gt;
+
+ &lt;propertyselector property="pack.list"
+ delimiter=","
+ match="package\.([^\.]*)\.name"
+ select="\1"
+ casesensitive="false" /&gt;
+
+ </code>
+ </pre>
+
+ would yield the results
+
+ <pre>
+ <code>
+ ABC,DEF,GHI,JKL
+ </code>
+ </pre>
+
+ You could then iterate through this list using the <a href="foreach.html"
+ >ForEach Task</a> as follows:
+
+ <pre>
+ <code>
+ &lt;foreach list="${pack.list}"
+ delimiter=","
+ target="print.name"
+ param="pack.id" /&gt;
+
+ &lt;target name="print.name" &gt;
+ &lt;propertycopy name="pack.name" value="package.${pack.id}.name" /&gt;
+ &lt;echo message="${pack.name}" /&gt;
+ &lt;/target&gt;
+ </code>
+ </pre>
+
+ Would print
+
+ <pre>
+ <code>
+ [echo] abc pack name
+ [echo] def pack name
+ [echo] ghi pack name
+ [echo] jkl pack name
+ </code>
+ </pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/runtarget.html b/docs/manual/tasks/runtarget.html
new file mode 100644
index 0000000..c2af7da
--- /dev/null
+++ b/docs/manual/tasks/runtarget.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: RunTarget</title>
+ </head>
+
+ <body>
+ <h1>RunTarget</h1>
+ <p>
+ Ant task that runs a target without creating a new project.
+ </p>
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">target</td>
+ <td valign="top">The name of the target to run.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </table>
+
+ <hr />
+
+ <h2>Example</h2>
+ <pre>
+ <code>
+ TO BE DONE
+ </code>
+ </pre>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/server_tasks.html b/docs/manual/tasks/server_tasks.html
new file mode 100644
index 0000000..5122be0
--- /dev/null
+++ b/docs/manual/tasks/server_tasks.html
@@ -0,0 +1,260 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Server Tasks</title>
+ </head>
+
+ <body>
+ <h1>Ant-Contrib Server Tasks</h1>
+
+ <p>The following tasks exist for running Ant server on one machine, and
+ calling that server from another (or possibly the same) machine, to
+ execute tasks.</p>
+
+
+ <hr width="100%" />
+
+ <h1>AntServer</h1>
+
+ <p>
+ Starts an ANT server in current process. This server will wait for
+ client connections, and when received, it will execute the commands
+ that the client has sent. NOTE: This is a blocking call, and this
+ task will not return until someone sends the server a shutdown command.
+ </p>
+
+ <h2>Parameters</h2>
+
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">port</td>
+ <td valign="top">The port on which the server will listen.</td>
+ <td align="center" valign="top">No. Defaults to 17000</td>
+ </tr>
+ </table>
+
+ <h2>Example:</h2>
+
+ <pre>
+ <code>
+ &lt;antserver port="12345" /&gt;
+ </code>
+ </pre>
+
+
+ <h1>RemoteAnt</h1>
+
+ <p>
+ Sends command requests to a running instance of an AntServer which
+ was started using the &lt;antserver&gt; task.
+ These commands are executed in the space of the server, and therefore
+ have no access to any variables or references in the currently executing
+ project.
+ </p>
+
+ <h2>Parameters</h2>
+
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">machine</td>
+ <td valign="top">The machine name on which the server is running.</td>
+ <td align="center" valign="top">No. Defaults to "localhost"</td>
+ </tr>
+ <tr>
+ <td valign="top">port</td>
+ <td valign="top">The port on which the server is listening.</td>
+ <td align="center" valign="top">No. Defaults to 17000</td>
+ </tr>
+ <tr>
+ <td valign="top">persistant</td>
+ <td valign="top">Should we execute all commands, regardless of whether
+ or not one of them fails. If false, as soon as a failure is encountered,
+ we will stop execution.</td>
+ <td align="center" valign="top">No. Defaults to false</td>
+ </tr>
+ <tr>
+ <td valign="top">failonerror</td>
+ <td valign="top">If any of the sent commands encounters a build failure on
+ the server, should we fail this task.</td>
+ <td align="center" valign="top">No. Defaults to true.</td>
+ </tr>
+ </table>
+
+ <h2>Parameters Specified as Nested Elements</h2>
+
+ <p>
+ The commands to send are represented as nested elements as described
+ below
+ </p>
+
+
+ <h3>runtarget</h3>
+
+ <p>Runs a target which is contained in the same buildfile where the
+ &lt;antserver&gt; task was called. This element may contain nested
+ &lt;property&gt; elements for sending parameters to the target, and
+ nested &lt;reference&gt; elements for sending references to the target.</p>
+
+ <h4>Parameters</h4>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">target</td>
+ <td valign="top">The name of the target to run.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </table>
+
+ <h3>runant</h3>
+
+ <p>Runs a target in an arbitrary buildfile on the machine where the
+ &lt;antserver&gt; task was called. If a relative pathname is given,
+ then the path of the buildfile is relative to the base directory of
+ the project where the &lt;antserver&gt; task was called. This element
+ may contain nested &lt;property&gt; elements for sending text parameters
+ to the target, and nested &lt;reference&gt; elements for sending references
+ to the target.</p>
+
+ <h4>Parameters</h4>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">antfile</td>
+ <td valign="top">The path of the ant file to run (if relative, then
+ the filename is computed relative to the buildfile of the server
+ task's base directory</td>
+ <td align="center" valign="top">No. Defaults to "build.xml" in the
+ directory where the buildfile is to execute (specified by the dir
+ attribute)</td>
+ </tr>
+ <tr>
+ <td valign="top">target</td>
+ <td valign="top">The name of the target to run.</td>
+ <td align="center" valign="top">No. Defaults to the default target of
+ the specified antfile.</td>
+ </tr>
+ <tr>
+ <td valign="top">dir</td>
+ <td valign="top">the directory to use as a basedir for the new Ant project. Defaults to
+ the server project's basedir, unless inheritall has been set to false, in which
+ case it doesn't have a default value. This will override the basedir setting of
+ the called project.</td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+ <tr>
+ <td valign="top">inheritall</td>
+ <td valign="top">Should the target task inherit all of
+ the server's properties. This is equivalent to the flag of
+ the same name on the &lt;ant&gt; task.</td>
+ <td align="center" valign="top">No. Defaults to false</td>
+ </tr>
+ <tr>
+ <td valign="top">inheritrefs</td>
+ <td valign="top">Should the target task inherit all of
+ the server's references. This is equivalent to the flag of
+ the same name on the &lt;ant&gt; task.</td>
+ <td align="center" valign="top">No. Defaults to false</td>
+ </tr>
+ </table>
+
+
+ <h3>shutdown</h3>
+
+ <p>Instructs the &lt;antserver&gt; task to shut itself down. Control
+ will return to the ANT engine and will procede as necessary in the
+ server's buildfile.</p>
+
+
+ <h2>Example:</h2>
+
+ <pre>
+ <code>
+ &lt;remoteant machine="localhost" port="12345"&gt;
+ &lt;runtarget target="execute.build"&gt;
+ &lt;property name="build.type" value="full" /&gt;
+ &lt;/runtarget&gt;
+ &lt;runant dir="tests" target="build.tests"&gt;
+ &lt;property name="build.type" value="full" /&gt;
+ &lt;reference refid="my.ref" torefid="inherited.ref" /&gt;
+ &lt;/runtarget&gt;
+ &lt;/remoteant&gt;
+ </code>
+ </pre>
+
+
+ <p>
+ would be the equivalent of running the following directly on
+ the server machine, from within the same buildfile where the
+ &lt;antserver&gt; task was run
+ </p>
+
+
+ <pre>
+ <code>
+ &lt;antcall target="execute.build"&gt;
+ &lt;param name="build.type" value="full" /&gt;
+ &lt;/antcall&gt;
+ &lt;ant dir="tests"&gt;
+ &lt;property name="build.type" value="full" /&gt;
+ &lt;reference refid="my.ref" torefid="inherited.ref" /&gt;
+ &lt;/antcall&gt;
+ </code>
+ </pre>
+
+ <h3>sendfile</h3>
+
+ <p>Sends a file from the client to the server</p>
+
+ <h4>Parameters</h4>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">file</td>
+ <td valign="top">The path of the file to send.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">tofile</td>
+ <td valign="top">The filename where the file is to be stored
+ on the server, if a relative path, then it is stored relative
+ to the server project's base directory.</td>
+ <td align="center" valign="top">No. If todir is specified</td>
+ </tr>
+ <tr>
+ <td valign="top">tofile</td>
+ <td valign="top">The directory where the file is to be stored
+ on the server, if a relative path, then it is stored relative
+ to the server project's base directory. The name of the file
+ will be the same name as the source file</td>
+ <td align="center" valign="top">No. If tofile is specified</td>
+ </tr>
+ </table>
+
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html> \ No newline at end of file
diff --git a/docs/manual/tasks/shellscript.html b/docs/manual/tasks/shellscript.html
new file mode 100644
index 0000000..34c4112
--- /dev/null
+++ b/docs/manual/tasks/shellscript.html
@@ -0,0 +1,140 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+<HEAD>
+ <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=utf-8">
+ <TITLE>Ant-contrib Tasks: ShellScript</TITLE>
+ <META NAME="GENERATOR" CONTENT="OpenOffice.org 644 (Linux)">
+ <META NAME="CREATED" CONTENT="20030313;10303100">
+ <META NAME="CHANGED" CONTENT="20030318;15221000">
+</HEAD>
+<BODY LANG="en-US" DIR="LTR">
+<H1>ShellScript</H1>
+<P>Task definition for the <CODE>shellscript</CODE> task. This task
+allows the user to execute a script against a particular shell
+program on a machine. It is an extension of the &quot;exec&quot;
+task, and as such, supports the same attributes. One can however use
+&quot;shell&quot; instead of &quot;executable&quot;. Also the
+&quot;command&quot; attribute is not allowed. See the ANT
+documentation for a description of the &lt;exec&gt; task parameters.</P>
+<H2>Parameters</H2>
+<TABLE WIDTH=854 BORDER=1 CELLPADDING=2 CELLSPACING=0>
+ <COL WIDTH=84>
+ <COL WIDTH=670>
+ <COL WIDTH=86>
+ <TR>
+ <TH WIDTH=84>
+ <P>Attribute</P>
+ </TH>
+ <TH WIDTH=670>
+ <P>Description</P>
+ </TH>
+ <TH WIDTH=86>
+ <P>Required</P>
+ </TH>
+ </TR>
+ <TR>
+ <TD WIDTH=84 VALIGN=TOP>
+ <P>shell</P>
+ </TD>
+ <TD WIDTH=670 VALIGN=TOP>
+ <P>The name of the shell executable which is to be executed. This
+ shell must support taking a single parameter whose value is a
+ script file which is to be executed.
+ </P>
+ </TD>
+ <TD WIDTH=86>
+ <P>Yes</P>
+ </TD>
+ </TR>
+ <TR>
+ <TD WIDTH=84 VALIGN=TOP>
+ <P>executable</P>
+ </TD>
+ <TD WIDTH=670 VALIGN=TOP>
+ <P>Same as “shell”</P>
+ </TD>
+ <TD WIDTH=86>
+ <P><BR>
+ </P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD WIDTH=84>
+ <P>tmpsuffix</P>
+ </TD>
+ <TD WIDTH=670>
+ <P>The contents of the script are placed in a temporary file. This
+ attribute is the extension to use. <B>note: </B>The value must
+ contain any dots required. This attribute is usefull for using
+ script files with windows
+ </P>
+ </TD>
+ <TD WIDTH=86>
+ <P>No</P>
+ </TD>
+ </TR>
+ <TR VALIGN=TOP>
+ <TD WIDTH=84>
+ <P>inputstring</P>
+ </TD>
+ <TD WIDTH=670>
+ <P>This is placed in the script file.</P>
+ </TD>
+ <TD WIDTH=86>
+ <P>No</P>
+ </TD>
+ </TR>
+</TABLE>
+<H2>Nested Text</H2>
+<P>Any nested text is treated as the contents of the script that is
+to be executed within the shell. Embedded ant properties will be
+converted.</P>
+<H2>Examples</H2>
+<PRE> &lt;shellscript shell=&quot;bash&quot; dir=&quot;${src.mib.dir}&quot;&gt;
+ mibgen -i ../include mib.mib -c ${build.gen.dir}/generated.cpp
+ mibgen -i ../include mib.mib -h ${build.gen.dir}/generated.h
+ &lt;/shellscript&gt;
+
+ &lt;shellscript shell=&quot;sed&quot; outputproperty=&quot;sed.output&quot;&gt;
+ &lt;arg value=&quot;-e&quot;/&gt;
+ &lt;arg value=&quot;s/FOO/BAR/g&quot;/&gt;
+ FOO bar bar bar FOO bar bar
+ &lt;/shellscript&gt;
+
+ &lt;shellscript shell=&quot;cmd.exe&quot; tmpsuffix=&quot;.bat&quot;&gt;
+ &lt;arg value=&quot;/c&quot;/&gt;
+ &lt;arg value=&quot;call&quot;/&gt;
+ echo hello world
+ &lt;/shellscript&gt;
+
+ &lt;shellscript shell=&quot;bash&quot;
+ dir=&quot;${build.bin.dir}&quot;
+ inputstring=&quot;ls -rt | tail -n 1&quot;
+ outputproperty=&quot;last.bin.file&quot;/&gt;
+
+ &lt;shellscript executable=&quot;perl&quot;&gt;
+ print STDOUT &quot;Hello World!\n&quot;;
+ &lt;/shellscript&gt;
+
+ &lt;shellscript shell=&quot;sh&quot; dir=&quot;${thirdparty.dist.dir}/lib&quot;&gt;
+ rm *.so
+ for file in *.0
+ do
+ x=`echo $file | sed -e's/.0.1.0//'`
+ ln -s $file $x
+ done
+ &lt;/shellscript&gt;</PRE><P>
+<BR><BR>
+</P>
+<P><B>Warning:</B></P>
+<P STYLE="margin-left: 0.79in">One should be carefull in using
+<I>shellscript</I>, as overuse will make your build files difficult
+to understand, to maintain and to support multiplatform builds. Use
+of <I>cygwin</I> in a windows environment will help. However one
+should strive to use the java tasks whereever possible.</P>
+<PRE STYLE="margin-bottom: 0.2in"> </PRE>
+<HR>
+<P ALIGN=CENTER>Copyright &copy; 2003 Ant-Contrib Project. All rights
+Reserved.</P>
+</BODY>
+</HTML> \ No newline at end of file
diff --git a/docs/manual/tasks/sortlist.html b/docs/manual/tasks/sortlist.html
new file mode 100644
index 0000000..5af5d41
--- /dev/null
+++ b/docs/manual/tasks/sortlist.html
@@ -0,0 +1,145 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: SortList</title>
+ </head>
+
+ <body>
+ <h1>SortList</h1>
+
+ <p>Sort a delimited list of items in their natural string order. Note that
+ the <code>value</code> and <code>refid</code> attributes are mutually exclusive,
+ and the <code>value</code> attribute takes precedence if both are specified.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">override</td>
+ <td valign="top">If the property is already set, should we change it's value.
+ Can be <code>true</code> or <code>false</code></td>
+ <td align="center" valign="top">No. Defaults to <code>false</code></td>
+ </tr>
+ <tr>
+ <td valign="top">value</td>
+ <td valign="top">The list of values to process, with the
+ delimiter character, indicated by the &quot;delimiter&quot;
+ attribute, separating each value.</td>
+ <td align="center" valign="top">Yes, unless &quot;refid&quot; is
+ specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">refid</td>
+ <td valign="top">The id of where the list of values to sort is
+ stored.</td>
+ <td align="center" valign="top">Yes, unless &quot;value&quot; is
+ specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">delimiter</td>
+ <td valign="top">The delimiter string that separates the
+ values in the &quot;list&quot; attribute.</td>
+ <td align="center" valign="top">No, defaults to &quot;,&quot;.</td>
+ </tr>
+ <tr>
+ <td valign="top">casesensitive</td>
+ <td valign="top">If <code>true</code>, does a case sensitive sorting
+ of the strings. If <code>false</code> does case insensitive sorting.
+ </td>
+ <td align="center" valign="top">No. Defaults to true.</td>
+ </tr>
+ <tr>
+ <td valign="top">numeric</td>
+ <td valign="top">If <code>true</code>, does a numeric sorting, treating
+ all list entries as if they were numbers.
+ </td>
+ <td align="center" valign="top">No. Defaults to false.</td>
+ </tr>
+
+ <tr>
+ <td valign="top">orderPropertyFile</td>
+ <td valign="top">If specified, the list will sorted as if they were property
+ names, and will be sorted in the order those properties appear
+ in the given property file. Any properties in the
+ <code>value</code> attribute which do not appear in the properties file
+ will be inserted at the end of the list. This property is most useful
+ when used in conjunction with the <code>&lt;propertyselector&gt;</code>
+ task (see Example 2).
+ </td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+
+ <tr>
+ <td valign="top">orderPropertyFilePrefix</td>
+ <td valign="top">If <code>orderPropertyFile</code> is specified, this
+ value (with a trailing '.') will be prefixed to each property in the
+ specified <code>orderPropertyFile</code> to determine sorting order
+ </td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+
+ </table>
+
+ <hr />
+
+ <h2>Example 1</h2>
+ <pre>
+ <code>
+ &lt;property name="my.list" value="z,y,x,w,v,u,t" /&gt;
+ &lt;sortlist property="my.sorted.list" value="${my.list}"
+ delimiter="," /&gt;
+ &lt;echo message="${my.sorted.list}" /&gt;
+ </code>
+
+ prints
+
+ <code>
+ [echo] t,u,v,w,x,y,z
+ </code>
+
+ <h2>Example 2</h2>
+ <pre>
+ test.properties
+ ---------------
+ a.name=a
+ c.name=c
+ b.name=b
+
+ <code>
+ &lt;property file="test.properties" prefix="test" /&gt;
+ &lt;propertyselector property="my.list"
+ delimiter=","
+ match="test\..*\.name"
+ select="\0" /&gt;
+ &lt;sortlist property="my.sorted.list"
+ value="${my.list}"
+ delimiter=","
+ orderPropertyFile="test.properties"
+ orderPropertyFilePrefix="test" /&gt;
+
+ &lt;echo message="${my.sorted.list}" /&gt;
+
+ prints
+
+ <code>
+ [echo] test.a.name,test.c.name,test.b.name
+ </code>
+
+ Notice that the <code>test.properties</code> file did not have "test."
+ prefixing all the properties. The <code>orderPropertyFilePrefix</code> was
+ used to do that.
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/stopwatch_task.html b/docs/manual/tasks/stopwatch_task.html
new file mode 100644
index 0000000..8520c78
--- /dev/null
+++ b/docs/manual/tasks/stopwatch_task.html
@@ -0,0 +1,115 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Stopwatch</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch08.html" title="Chapter&nbsp;8.&nbsp;Variable Task">
+<link rel="next" href="bk03ch10.html" title="Chapter&nbsp;10.&nbsp;Limit">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="stopwatch">
+</a>
+Stopwatch</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The Stopwatch task makes it easy to add performance timing to Ant targets. Stopwatches are named so that multiple watches can run simultaneously.
+</p>
+
+<p>
+
+<div class="table">
+<a name="N1092E">
+</a>
+<p class="title">
+<b>
+Table&nbsp;9.1.&nbsp;Stopwatch Task Attributes</b>
+</p>
+<table summary="Stopwatch Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+name</td>
+<td>
+The name for the stopwatch. The elapsed time or total time will be stored as an Ant property with this name.</td>
+<td>
+None</td>
+<td>
+Yes</td>
+</tr>
+<tr>
+<td>
+action</td>
+<td>
+Valid values are "start", "stop", "elapsed", and "total".</td>
+<td>
+"start"</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+The stopwatch is started with the "start" action. When the action is "elapsed" or "total", the running time of the stopwatch is printed out. Both "stop" and "total" stop the stopwatch and reset it to zero. "elapsed" prints out the current running time of the stopwatch without stopping it.
+</p>
+<p>
+
+Example:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+&lt;stopwatch name="timer1"/&gt;
+&lt;!-- do some tasks here... --&gt;
+&lt;stopwatch name="timer1" action="elapsed"/&gt; &lt;!-- print the elapsed time --&gt;
+&lt;!-- do some more tasks here... --&gt;
+&lt;stopwatch name="timer1" action="total"/&gt; &lt;!-- print out the total time --&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/switch.html b/docs/manual/tasks/switch.html
new file mode 100644
index 0000000..837c701
--- /dev/null
+++ b/docs/manual/tasks/switch.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Switch</title>
+ </head>
+
+ <body>
+ <h1>Switch</h1>
+
+ <p>Task definition for the ANT task to switch on a particular value.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">value</td>
+ <td valign="top">The value to switch on.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">caseinsensitive</td>
+ <td valign="top">Should we do case insensitive comparisons?</td>
+ <td align="center" valign="top">No, default is &quot;false&quot;</td>
+ </tr>
+ </table>
+
+ <h2>Parameters specified as nested elements</h2>
+
+ <p>At least one <code>&lt;case&gt;</code> or
+ <code>&lt;default&gt;</code> is required.</p>
+
+ <h3>case</h3>
+
+ <p>An individual case to consider, if the value that is being
+ switched on matches to value attribute of the case, then the
+ nested tasks will be executed.</p>
+
+ <h4>Parameters</h4>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">value</td>
+ <td valign="top">The value to match against the tasks value attribute.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ </table>
+
+ <h3>default</h3>
+
+ <p>The default case for when no match is found. Must not appear
+ more than once per task.</p>
+
+ <h2>Example</h2>
+
+<pre>
+&lt;switch value=&quot;${foo}&quot;&gt;
+ &lt;case value=&quot;bar&quot;&gt;
+ &lt;echo message=&quot;The value of property foo is bar&quot; /&gt;
+ &lt;/case&gt;
+ &lt;case value=&quot;baz&quot;&gt;
+ &lt;echo message=&quot;The value of property foo is baz&quot; /&gt;
+ &lt;/case&gt;
+ &lt;default&gt;
+ &lt;echo message=&quot;The value of property foo is not sensible&quot; /&gt;
+ &lt;/default&gt;
+&lt;/switch&gt;
+</pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/throw.html b/docs/manual/tasks/throw.html
new file mode 100644
index 0000000..0aeb0e8
--- /dev/null
+++ b/docs/manual/tasks/throw.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Throw</title>
+ </head>
+
+ <body>
+ <h1>Throw</h1>
+
+ <p>Extension of Ant's built-in <code>&lt;fail&gt;</code> task that
+ can throw an exception that is given by a reference. This may be
+ useful if you want to rethrow the exception that has been caught
+ by a <code>&lt;trycatch&gt;</code> task in the
+ <code>&lt;catch&gt;</code> block.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">refid</td>
+ <td valign="top">Id of the referenced exception.</td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+ </table>
+
+ <p>In addition, all attributes of the <a
+ href="http://jakarta.apache.org/ant/manual/CoreTasks/fail.html"><code>&lt;fail&gt;</code>
+ task</a> are supported.</p>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/timestampselector.html b/docs/manual/tasks/timestampselector.html
new file mode 100644
index 0000000..c4186d1
--- /dev/null
+++ b/docs/manual/tasks/timestampselector.html
@@ -0,0 +1,132 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: TimestampSelector</title>
+ </head>
+
+ <body>
+ <h1>TimestampSelector</h1>
+
+ <p>The TimestampSelector task takes either a nested &lt;path&gt; element,
+ or a path reference, and sets either a named property, or a <code>path</code>
+ instance to absolute pathnames of the files with either the N latest or earliest
+ modification dates (based on the <code>age</code> attribute)</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The property to set with the most recently modified file. Mutually
+ exclusive with the <code>outputsetid</code> attribute.</td>
+ <td align="center" valign="top">Yes, if <code>outputsetid</code> is not specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">outputsetid</td>
+ <td valign="top">The id of a <code>path</code> instance which will contain the
+ resulting list of files. This id should not already exist. Mutually exclusive
+ with the <code>property</code> attribute</td>
+ <td align="center" valign="top">Yes, if <code>property</code> is note specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">count</td>
+ <td valign="top">The number of files to find. If more than 1, than the
+ files in the output appear in the order indicated by the <code>age</code>
+ attribute.</td>
+ <td align="center" valign="top">No. Defaults to <code>1<code></td>
+ </tr>
+ <tr>
+ <td valign="top">age</td>
+ <td valign="top">The age of the files to retrieve, either <code>eldest</code>
+ or <code>youngest</code>. Defaults to <code>youngest</code>.</td>
+ <td align="center" valign="top">No. Defaults to <code>1<code></td>
+ </tr>
+ <tr>
+ <td valign="top">pathSep</td>
+ <td valign="top">The path separator to separate paths with when using the
+ <code>property</code> attribute in conjunction with the <code>count</code>
+ attribute</td>
+ <td align="center" valign="top">No. Defaults to <code>,<code></td>
+ </tr>
+ <tr>
+ <td valign="top">pathref</td>
+ <td valign="top">Id of the path to find the most recently modified file in.</td>
+ <td align="center" valign="top">No, if a <code>path</code> subelement is
+ specified.</td>
+ </tr>
+ </table>
+
+ <h2>Parameters specified as nested elements</h2>
+
+ <a name="path"><h3>path</h3></a>
+
+ <p><a href="http://ant.apache.org/manual/using.html#path">Path</a>
+ is used to select sets of files or directories in which to find the
+ most recently modified file</p>
+
+ <h2>Example</h2>
+
+ <h3>Using a path reference</h3>
+ <pre>
+ <code>
+
+ &lt;path id="mypath"&gt;
+ &lt;fileset dir="${log.dir}"&gt;
+ &lt;include name="update*.log" /&gt;
+ &lt;/fileset&gt;
+ &lt;path&gt;
+ &lt;timestampselector property="most.recent.logs"
+ pathref="mypath" count="3"
+ pathsep=";" /&gt;
+
+ &lt;echo message="${most.recent.logs}" /&gt;
+ </code>
+ </pre>
+
+ <h3>Using a nested <code>path</code> element</h3>
+ <pre>
+ <code>
+
+ &lt;timestampselector property="most.recent.logs"
+ count="3"
+ pathsep=";" &gt;
+ &lt;path&gt;
+ &lt;fileset dir="${log.dir}"&gt;
+ &lt;include name="update*.log" /&gt;
+ &lt;/fileset&gt;
+ &lt;path&gt;
+ &lt;/timestampselector&gt;
+
+ &lt;echo message="${most.recent.logs}" /&gt;
+ </code>
+ </pre>
+
+ <h3>Outputing to a <code>path</code> element</h3>
+ <pre>
+ <code>
+
+ &lt;timestampselector outputsetref="most.recent.logs"
+ pathref="mypath" count="3"&gt;
+ &lt;path&gt;
+ &lt;fileset dir="${log.dir}"&gt;
+ &lt;include name="update*.log" /&gt;
+ &lt;/fileset&gt;
+ &lt;path&gt;
+ &lt;/timestampselector&gt;
+
+ &lt;copy todir="somedir"&gt;
+ &lt;path refid="most.recent.logs" /&gt;
+ &lt;/copy&gt;
+ </code>
+ </pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/toc.html b/docs/manual/tasks/toc.html
new file mode 100644
index 0000000..b1d926f
--- /dev/null
+++ b/docs/manual/tasks/toc.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Task List</title>
+ </head>
+
+ <body>
+ <h2>Logic Tasks</h2>
+ <ul>
+ <li><a href="antcallback_task.html" target="mainFrame">AntCallBack</a></li>
+ <li><a href="antfetch_task.html" target="mainFrame">AntFetch</a></li>
+ <li><a href="assert_task.html" target="mainFrame">Assert</a></li>
+ <li><a href="foreach.html" target="mainFrame">Foreach</a></li>
+ <li><a href="for.html" target="mainFrame">For</a></li>
+ <li><a href="if.html" target="mainFrame">If</a></li>
+ <li><a href="outofdate.html" target="mainFrame">Outoutdate</a></li>
+ <li><a href="runtarget.html" target="mainFrame">RunTarget</a></li>
+ <li><a href="switch.html" target="mainFrame">Switch</a></li>
+ <li><a href="throw.html" target="mainFrame">Throw</a></li>
+ <li><a href="timestampselector.html" target="mainFrame">TimestampSelector</a></li>
+ <li><a href="trycatch.html" target="mainFrame">Trycatch</a></li>
+ </ul>
+ <h2>Network Tasks</h2>
+ <ul>
+ <li><a href="post_task.html" target="mainFrame">HTTP Post</a></li>
+ <li><a href="server_tasks.html" target="mainFrame">AntServer / RemoteAnt</a></li>
+ </ul>
+ <h2>Performance Monitoring and Tasks</h2>
+ <ul>
+ <li><a href="performance_monitor.html" target="mainFrame">Performance Monitor</a></li>
+ <li><a href="stopwatch_task.html" target="mainFrame">Stopwatch</a></li>
+ </ul>
+ <h2>Platform Tasks</h2>
+ <ul>
+ <li><a href="osfamily.html" target="mainFrame">Osfamily</a></li>
+ <li><a href="shellscript.html" target="mainFrame">Shellscript</a></li>
+ </ul>
+ <h2>Property Tasks</h2>
+ <ul>
+ <li><a href="math_task.html" target="mainFrame">Math</a></li>
+ <li><a href="propertycopy.html" target="mainFrame">Propertycopy</a></li>
+ <li><a href="propertyselector.html" target="mainFrame">PropertySelector</a></li>
+ <li><a href="pathtofileset.html" target="mainFrame">Pathtofileset</a></li>
+ <li><a href="propertyregex.html" target="mainFrame">PropertyRegex</a></li>
+ <li><a href="sortlist.html" target="mainFrame">SortList</a></li>
+ <li><a href="urlencode.html" target="mainFrame">URLEncode</a></li>
+ <li><a href="variable_task.html" target="mainFrame">Variable</a></li>
+ </ul>
+
+ <h2>Process Tasks</h2>
+ <ul>
+ <li><a href="forget.html" target="mainFrame">Forget</a></li>
+ <li><a href="limit_task.html" target="mainFrame">Limit</a></li>
+ </ul>
+
+ <h2>Other Tasks</h2>
+ <ul>
+ <li><a href="antclipse_task.html" target="mainFrame">antclipse</a></li>
+ <li><a href="compilewithwalls.html" target="mainFrame">CompileWithWalls</a></li>
+ <li><a href="inifile.html" target="mainFrame">IniFile</a></li>
+ <li><a href="verifydesign.html" target="mainFrame">VerifyDesign</a></li>
+ </ul>
+ </body>
+</html>
diff --git a/docs/manual/tasks/trycatch.html b/docs/manual/tasks/trycatch.html
new file mode 100644
index 0000000..7eb38a8
--- /dev/null
+++ b/docs/manual/tasks/trycatch.html
@@ -0,0 +1,96 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: Trycatch</title>
+ </head>
+
+ <body>
+ <h1>Trycatch</h1>
+
+ <p>A wrapper that lets you run a set of tasks and optionally run a
+ different set of tasks if the first set fails and yet another set
+ after the first one has finished.</p>
+
+ <p>This mirrors Java's try/catch/finally.</p>
+
+ <p>The tasks inside of the required <code>&lt;try&gt;</code>
+ element will be run. If one of them should throw a BuildException
+ several things can happen:</p>
+
+ <ul>
+ <li>If there is no <code>&lt;catch&gt;</code> block, the
+ exception will be passed through to Ant.</li>
+
+ <li>If the property attribute has been set, a property of the
+ given name will be set to the message of the exception.</li>
+
+ <li>If the reference attribute has been set, a reference of the
+ given id will be created and point to the exception object.</li>
+
+ <li>If there is a <code>&lt;catch&gt;</code> block, the tasks
+ nested into it will be run.</li>
+ </ul>
+
+ <p>If a <code>&lt;finally&gt;</code> block is present, the task
+ nested into it will be run, no matter whether the first tasks have
+ thrown an exception or not.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">Name of a property that will receive the
+ message of the exception that has been caught (if any)</td>
+ <td align="center" valign="top">No.</td>
+ </tr>
+ <tr>
+ <td valign="top">reference</td>
+ <td valign="top">Id of a reference that will point to the
+ exception object that has been caught (if any)</td>
+ <td align="center" valign="top">No</td>
+ </tr>
+ </table>
+
+ <h2>Example</h2>
+
+<pre>
+&lt;trycatch property=&quot;foo&quot; reference=&quot;bar&quot;&gt;
+ &lt;try&gt;
+ &lt;fail&gt;Tada!&lt;/fail&gt;
+ &lt;/try&gt;
+
+ &lt;catch&gt;
+ &lt;echo&gt;In &amp;lt;catch&amp;gt;.&lt;/echo&gt;
+ &lt;/catch&gt;
+
+ &lt;finally&gt;
+ &lt;echo&gt;In &amp;lt;finally&amp;gt;.&lt;/echo&gt;
+ &lt;/finally&gt;
+&lt;/trycatch&gt;
+
+&lt;echo&gt;As property: ${foo}&lt;/echo&gt;
+&lt;property name=&quot;baz&quot; refid=&quot;bar&quot; /&gt;
+&lt;echo&gt;From reference: ${baz}&lt;/echo&gt;
+</pre>
+
+ <p>results in</p>
+
+<pre>
+ [trycatch] Caught exception: Tada!
+ [echo] In &lt;catch&gt;.
+ [echo] In &lt;finally&gt;.
+ [echo] As property: Tada!
+ [echo] From reference: Tada!
+</pre>
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/urlencode.html b/docs/manual/tasks/urlencode.html
new file mode 100644
index 0000000..be6a322
--- /dev/null
+++ b/docs/manual/tasks/urlencode.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+ <head>
+ <title>Ant-contrib Tasks: URLEncode</title>
+ </head>
+
+ <body>
+ <h1>Foreach</h1>
+
+ <p>The URLEncode task will encode a given property for use within a
+ a URL string. This value which is actually set will be encoded
+ via the <code>java.net.URLEncoder.encode()</code> method.
+ Typically, you must do this for all parameter values within a URL.</p>
+
+ <h2>Parameters</h2>
+ <table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <th>Attribute</th>
+ <th>Description</th>
+ <th>Required</th>
+ </tr>
+ <tr>
+ <td valign="top">property</td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">Yes.</td>
+ </tr>
+ <tr>
+ <td valign="top">override</td>
+ <td valign="top">If the property is already set, should we change it's value.
+ Can be <code>true</code> or <code>false</code></td>
+ <td align="center" valign="top">No. Defaults to <code>false</code></td>
+ </tr>
+ <tr>
+ <td valign="top">name <i>Deprecated</i></td>
+ <td valign="top">The name of the property to set.</td>
+ <td align="center" valign="top">No. Use the <code>property</code> attribute
+ instead</td>
+ </tr>
+ <tr>
+ <td valign="top">value</td>
+ <td valign="top">The value of the property.</td>
+ <td align="center" valign="top">No, if refid or location is specified</td>
+ </tr>
+ <tr>
+ <td valign="top">location</td>
+ <td valign="top">The location of a file whose absolute path will be the value
+ of the property.</td>
+ <td align="center" valign="top">No, if value or refid is specified.</td>
+ </tr>
+ <tr>
+ <td valign="top">refid</td>
+ <td valign="top">The id of a saved reference whose value will be the value
+ of the property.</td>
+ <td align="center" valign="top">No, defaults to &quot;,&quot;.</td>
+ </tr>
+ </table>
+
+
+ <h2>Example</h2>
+
+
+ The following code
+
+ <pre>
+ <code>
+ &lt;urlencode name="file.location" location="C:\\wwwhome\\my reports\\report.xml" /&gt;
+ </code>
+ </pre>
+
+ would set the "file.location" property to the value: <code> C%3A%5Cwwwhome%5Cmy+reports%5Creport.xml</code>
+ which could then be used in a URL.
+
+ <hr>
+ <p align="center">Copyright &copy; 2002-2003 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+ </body>
+</html>
diff --git a/docs/manual/tasks/variable_task.html b/docs/manual/tasks/variable_task.html
new file mode 100644
index 0000000..7e16ab9
--- /dev/null
+++ b/docs/manual/tasks/variable_task.html
@@ -0,0 +1,261 @@
+<html>
+<head>
+<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+<title>
+Variable Task</title>
+<meta content="DocBook XSL Stylesheets V1.60.1" name="generator">
+<link rel="home" href="index.html" title="Antelope Users Guide">
+<link rel="up" href="bk03.html" title="Additional Ant Tasks">
+<link rel="previous" href="bk03ch07.html" title="Chapter&nbsp;7.&nbsp;Try Task">
+<link rel="next" href="bk03ch09.html" title="Chapter&nbsp;9.&nbsp;Stopwatch">
+</head>
+<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
+<div class="chapter" lang="en">
+<div class="titlepage">
+<div>
+<div>
+<h2 class="title">
+<a name="Variable">
+</a>
+Chapter&nbsp;8.&nbsp;Variable Task</h2>
+</div>
+</div>
+<div>
+</div>
+</div>
+<p>
+
+The Variable task provides a mutable property to Ant and works much like variable assignment in Java. This task is similar to the standard Ant Property task, except that THESE PROPERTIES ARE MUTABLE. While this goes against the standard Ant use of properties, occasionally it is useful to be able to change a property value within the build. <span class="bold">
+<b>
+In general, use of this task is DISCOURAGED, and the standard Ant Property should be used if possible.</b>
+</span>
+ Having said that, in real life I use this a lot.
+</p>
+
+<p>
+
+Variables can be set individually or loaded from a standard properties file. A 'feature' of variables is that they can override properties, but properties cannot override variables. So if an already established property exists, its value can be reassigned by use of this task.
+</p>
+<p>
+
+<div class="table">
+<a name="N108CD">
+</a>
+<p class="title">
+<b>
+Table&nbsp;8.1.&nbsp;Variable Task Attributes</b>
+</p>
+<table summary="Variable Task Attributes" border="1">
+<colgroup>
+<col>
+<col>
+<col>
+<col>
+</colgroup>
+<thead>
+<tr>
+<th>
+Attribute</th>
+<th>
+Description</th>
+<th>
+Default</th>
+<th>
+Required</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td>
+name</td>
+<td>
+The name of the property to set.</td>
+<td>
+None</td>
+<td>
+Yes, unless 'file' is used.</td>
+</tr>
+<tr>
+<td>
+value</td>
+<td>
+The value of the property.</td>
+<td>
+""</td>
+<td>
+No</td>
+</tr>
+<tr>
+<td>
+unset</td>
+<td>
+Removes the property from the project as if it had never been set.</td>
+<td>
+false
+</td>
+<td>
+No
+</td>
+</tr>
+<tr>
+<td>
+file</td>
+<td>
+The name of a standard properties file to load variables from.</td>
+<td>
+None</td>
+<td>
+No</td>
+</tr>
+</tbody>
+</table>
+</div>
+
+</p>
+<p>
+
+In the following example, the property <tt class="computeroutput">
+x</tt>
+ is first set to "6", then evaluated by the <tt class="computeroutput">
+if</tt>
+, and reassigned the value "12". The <tt class="computeroutput">
+echo</tt>
+ task will print out 12.
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;var name="x" value="6"/&gt;
+ &lt;if&gt;
+ &lt;equals arg1="${x}" arg2="6" /&gt;
+ &lt;then&gt;
+ &lt;var name="x" value="12"/&gt;
+ &lt;/then&gt;
+ &lt;/if&gt;
+ &lt;echo&gt;${x}&lt;/echo&gt; &lt;!-- will print 12 --&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+
+<p>
+The next example shows a property being set, echoed, unset, then reset:
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;property name="x" value="6"/&gt;
+ &lt;echo&gt;${x}&lt;/echo&gt; &lt;!-- will print 6 --&gt;
+ &lt;var name="x" unset="true"/&gt;
+ &lt;property name="x" value="12"/&gt;
+ &lt;echo&gt;${x}&lt;/echo&gt; &lt;!-- will print 12 --&gt;
+
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+
+<p>
+
+The following shows some more uses of the Variable task. It is especially handy for property appending. Notice a couple of things: the property task can't override a var value, in general, you should use var with the unset attribute to change the value of a property.
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;var name="x" value="6"/&gt;
+ &lt;echo&gt;x = ${x}&lt;/echo&gt; &lt;!-- print: 6 --&gt;
+
+ &lt;var name="x" value="12"/&gt;
+ &lt;echo&gt;x = ${x}&lt;/echo&gt; &lt;!-- print: 12 --&gt;
+
+ &lt;var name="x" value="6 + ${x}"/&gt;
+ &lt;echo&gt;x = ${x}&lt;/echo&gt; &lt;!-- print: 6 + 12 --&gt;
+
+ &lt;var name="str" value="I "/&gt;
+ &lt;var name="str" value="${str} am "/&gt;
+ &lt;var name="str" value="${str} a "/&gt;
+ &lt;var name="str" value="${str} string."/&gt;
+ &lt;echo&gt;${str}&lt;/echo&gt; &lt;!-- print: I am a string. --&gt;
+
+ &lt;var name="x" value="6"/&gt;
+ &lt;echo&gt;x = ${x}&lt;/echo&gt; &lt;!-- print: 6 --&gt;
+
+ &lt;property name="x" value="12"/&gt;
+ &lt;echo&gt;x = ${x}&lt;/echo&gt; &lt;!-- print: 6 (property can't override) --&gt;
+
+ &lt;var name="x" value="blue"/&gt;
+ &lt;tstamp&gt;
+ &lt;format property="x" pattern="EEEE"/&gt;
+ &lt;/tstamp&gt;
+ &lt;echo&gt;Today is ${x}.&lt;/echo&gt; &lt;!-- print: Today is blue. --&gt;
+
+ &lt;var name="x" value="" unset="true"/&gt;
+ &lt;tstamp&gt;
+ &lt;format property="x" pattern="EEEE"/&gt;
+ &lt;/tstamp&gt;
+ &lt;echo&gt;Today is ${x}.&lt;/echo&gt; &lt;!-- print: Today is Friday. --&gt;
+
+
+</pre>
+</td>
+</tr>
+</table>
+
+</p>
+<p>
+
+<!--
+The next example shows Variable, If, Assert, and Try working together to make sure e-mail is sent from the right address and that if the mail fails to be sent for any reason, the build will not fail.
+</p>
+<p>
+
+<table border="0" bgcolor="#E0E0E0">
+<tr>
+<td>
+<pre class="programlisting">
+
+
+ &lt;var name="valid_email" value="false"/&gt;
+ &lt;if name="email_from" value="[email protected]"&gt;
+ &lt;var name="valid_email" value="true"/&gt;
+ &lt;/if&gt;
+ &lt;if name="email_from" value="[email protected]"&gt;
+ &lt;var name="valid_email" value="true"/&gt;
+ &lt;/if&gt;
+ &lt;assert name="valid_email" value="true" failonerror="false"&gt;
+ &lt;try&gt;
+ &lt;mail from="${email_from}" tolist="${email_to}"
+ message="New release available"/&gt;
+ &lt;/try&gt;
+ &lt;/assert&gt;
+
+</pre>
+</td>
+</tr>
+</table>
+-->
+</p>
+</div>
+ <hr>
+ <p align="center">Copyright &copy; 2003-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+</body>
+</html>
diff --git a/docs/manual/tasks/verifydesign.html b/docs/manual/tasks/verifydesign.html
new file mode 100644
index 0000000..80f1588
--- /dev/null
+++ b/docs/manual/tasks/verifydesign.html
@@ -0,0 +1,264 @@
+<html lang="en-us">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>VerifyDesign Ant Task</title>
+</head>
+
+<body>
+
+<h2>VerifyDesign Ant Task</h2>
+<ul>
+ <li>Creator: Dean Hiller (<a href="mailto:[email protected]">[email protected]</a>)</li>
+ <li>Contributor: Matt Inger (thanks for some really awesome changes)</li>
+ <li>Contributor: Anthony Y Robins</li>
+</ul>
+<p>Feedback on task and documentation are welcome!</p>
+<h3>Description</h3>
+<p>Describe your design dependencies in an xml file, and this task will enforce them so they are not violated</p>
+<p>For example, if there are three packages in one source tree
+<ul>
+<li>biz.xsoftware.presentation</li>
+<li>biz.xsoftware.business</li>
+<li>biz.xsoftware.dataaccess</li>
+</ul>
+and naturally presentation should only depend on business package, and business should depend on dataaccess. If you define your design this way and it is violated the build will fail when the verifydesign ant task is called. For example, if I created a class in biz.xsoftware.presentation and that class depended on a class in biz.xsoftware.dataaccess, the build would fail. This ensures the design actually follows what is documented(to some degree at least). This is especially nice with automated builds</p>
+
+<h3>Getting Started</h3>
+Download bcel jar from this link <a href="http://jakarta.apache.org/site/binindex.cgi#bcel">Bcel download</a> as this ant task uses the jar built from the <a href="http://jakarta.apache.org/bcel/">bcel project</a> on jakarta. Choose a directory to put in place of the XXXXXX below and add the ant-contrib jar as well as the bcel jar to that directory. You should now be all set to use the verifydesign element in your build.xml file as well as any other ant-contrib tasks. If you want to use this with 5.0jdk, you must download the bcel from the head of cvs until something better than 5.1 is released. This version of ant-contrib will work with both 5.0jdk and 1.4 jdk. 1.3 and before is not tested.
+<pre>
+ &lt;taskdef resource=&quot;net/sf/antcontrib/antlib.xml&quot;&gt;
+ &lt;classpath&gt;
+ &lt;fileset dir=&quot;XXXXXX&quot;&gt;
+ &lt;include name=&quot;**/*.jar&quot;/&gt;
+ &lt;/fileset&gt;
+ &lt;/classpath&gt;
+ &lt;/taskdef&gt;
+</pre>
+
+Now, you can skip to the <a href="verifylegacytutorial.html">VerifyDesign Legacy Project Tutorial</a> which guides you through how to use this task if you already have alot of existing code, or you can start with the <a href="verifynewprojtutorial.html">VerifyDesign New Project Tutorial</a> where you don't have much code or any at all.
+
+<h3>Parameters</h3>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">design</td>
+ <td valign="top">The file that specifies the design in xml format(Examples below)</td>
+ <td align="center" valign="top">required</td>
+ </tr>
+ <tr>
+ <td valign="top">jar</td>
+ <td valign="top">The jar file of who's design we want to validate</td>
+ <td align="center" valign="top">required</td>
+ </tr>
+ <tr>
+ <td valign="top">circularDesign</td>
+ <td valign="top">I strongly encourage you not to use this. This turns on allowing circular dependencies. There is always a way to get around circular dependencies, and I suggest you use it instead of introducing a circular dependency. If you think you have found one you can't work around, send me mail and maybe I can give you some ideas.</td>
+ <td align="center" valign="top">optional(default=false)</td>
+ </tr>
+ <tr>
+ <td valign="top">deleteFiles</td>
+ <td valign="top">Deletes jar/class files upon build failure to prevent usage. Use this option for new projects so the binaries are not used without the design being met. </td>
+ <td align="center" valign="top">optional(default=false)</td>
+ </tr>
+ <tr>
+ <td valign="top">fillInBuildException</td>
+ <td valign="top">Fills the BuildException with all the same errors reported in the logs. This is for products like cruisecontrol who only see standard ant task logs and would miss reporting these errors otherwise(ie. instead it just reports build failed with look at the design errors)</td>
+ <td align="center" valign="top">optional(default=false)</td>
+ </tr>
+ <tr>
+ <td valign="top">needDeclarationsDefault</td>
+ <td valign="top">false is saying that for this particular package, no other package needs to declare that they depend on this package. It is basically saying the needDeclarations attribute in the package element in the design file is whatever the value of this attribute is in the build.xml file if the design file does not override it.</td>
+ <td align="center" valign="top">optional(default=true)</td>
+ </tr>
+ <tr>
+ <td valign="top">needDependsDefault</td>
+ <td valign="top">false is saying that by default no package in the design file has to declare it's dependencies. It is basically saying the needDepends attribute in the package element in the design file is whatever the value of this attribute is in the build.xml file if the design file does not override it.</td>
+ <td align="center" valign="top">optional(default=true)</td>
+ </tr>
+</table>
+
+<h3>Parameters specified as nested elements</h3>
+<p>No nested elements allowed
+
+
+</p>
+<h2>Design File</h2>
+<p>
+The design file is an xml based file specifying dependencies that are ok. Any dependencies not specified will not be allowed and will make sure the build fails. Examples of the contents of the design file can be found below.
+</p>
+
+<h3>design Root Element</h3>
+<p>The root element of the design file is 'design'. Here are design's allowed subelements.</p>
+
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Subelement</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">package</td>
+ <td valign="top">subelement representing a package and it's dependencies</td>
+ <td align="center" valign="top">One or more Required</td>
+ </tr>
+</table>
+
+<h3>package SubElement</h3>
+<p>Here are package elements allowed attributes and subelements</p>
+
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Attribute</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">name</td>
+ <td valign="top">A smaller nickname for the package to reference in the depends subelement or attribute</td>
+ <td align="center" valign="top">Required</td>
+ </tr>
+ <tr>
+ <td valign="top">package</td>
+ <td valign="top">The package to compile such as biz.xsoftware.presentation</td>
+ <td align="center" valign="top">Required</td>
+ </tr>
+ <tr>
+ <td valign="top">depends</td>
+ <td valign="top">Contains one and only one 'name' of a package to depend on(taken from name attribute above). If you want to specify more, use the depends subelement</td>
+ <td align="center" valign="top">Optional(Default=no dependencies)</td>
+ </tr>
+ <tr>
+ <td valign="top">subpackages</td>
+ <td valign="top">Can be set to include or exclude. Basically allows classes in subpackages to be part of the package specified.(see examples below)</td>
+ <td align="center" valign="top">Optional(default=exclude)</td>
+ </tr>
+ <tr>
+ <td valign="top">needdeclarations</td>
+ <td valign="top">Can be set to true or false. True means if other packages depend on this package, a depends subelement or attribute must exist stating the dependency. False means other packages need not declare they depend on this package. This should be used sparingly for things like java.lang. By default &quot;java&quot; package and all subpackages are set to false. This can be overridden if you need however so you can make sure only certain packages depend on java.util or something if you really need that. (see examples below)</td>
+ <td align="center" valign="top">Optional(default=true)</td>
+ </tr>
+ <tr>
+ <td valign="top">needdepends</td>
+ <td valign="top">Can be set to true or false. True means if this package depends on other packages, those dependencies must be defined(unless those other packages have needdeclarations set to false). False means this package must list all the packages it depends on. This is typically for legacy code where you don't want to deal with what this package depends on right now. On a new project, I never use this.</td>
+ <td align="center" valign="top">Optional(default=true)</td>
+ </tr>
+</table>
+<br/>
+<table border="1" cellpadding="2" cellspacing="0">
+ <tr>
+ <td valign="top"><b>Subelement</b></td>
+ <td valign="top"><b>Description</b></td>
+ <td align="center" valign="top"><b>Required</b></td>
+ </tr>
+ <tr>
+ <td valign="top">depends</td>
+ <td valign="top">Contains one and only one 'name' of a package to depend on(taken from name attribute above)</td>
+ <td align="center" valign="top">One or more Optional</td>
+ </tr>
+</table>
+
+<h3>depends SubElement</h3>
+Contents contain the 'name' of a package found in the package element's name attribute
+
+<h3>Examples</h3>
+
+<h4>Ant's build.xml File</h4>
+<pre>
+ &lt;verifydesign jar=&quot;application.jar&quot; design=&quot;design.xml&quot;/&gt;
+</pre>
+<p>
+That is simple enough. application.jar is the jar I am verifying the design of. design.xml contains the design I want the jar file to adhere to. There is no need to include third party jars(unless you want to verify their design which you shouldn't). The design file can still define what your stuff depends on in those third party libraries without requiring those libraries to be present. If it does not adhere to that design, the build fails. Examples of a design.xml can be found further below.
+</p>
+<p>
+Another example equivalent to the above is below. verifydesign takes a path like structure(see ant documentation). <b>I highly advise breaking the design on purpose and verifying that the build fails. This ensures you have the ant task set up correctly.</b>
+</p>
+<pre>
+ &lt;verifydesign design=&quot;design.xml&quot;&gt;
+ &lt;path&gt;
+ &lt;pathelement jar=&quot;application.jar&quot;/&gt;
+ &lt;/path&gt;
+ &lt;/verifydesign&gt;
+</pre>
+
+One last example would be like so
+<pre>
+ &lt;verifydesign design=&quot;design.xml&quot;&gt;
+ &lt;path&gt;
+ &lt;fileset dir=&quot;${classesDir}&quot;&gt;
+ &lt;include name=&quot;**/*.class&quot;/&gt;
+ &lt;/fileset&gt;
+ &lt;/path&gt;
+ &lt;/verifydesign&gt;
+</pre>
+
+Now let's move on to define the contents of design.xml file.
+
+<h4>design.xml File</h4>
+
+<pre>
+These lines would be in dependencies.xml.....
+ &lt;design&gt;
+ &lt;package name=&quot;alljavax&quot; package=&quot;javax&quot; subpackages=&quot;include&quot; needdeclarations=&quot;false&quot;/&gt;
+ &lt;package name=&quot;util&quot; package=&quot;biz.xsoftware.util&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;package name=&quot;dataaccess&quot; package=&quot;biz.xsoftware.dataaccess&quot;/&gt;
+ &lt;package name=&quot;business&quot; package=&quot;biz.xsoftware.business&quot; depends=&quot;dataaccess&quot;/&gt;
+ &lt;package name=&quot;presentation&quot; package=&quot;biz.xsoftware.presentation&quot;&gt;
+ &lt;depends&gt;business&lt;/depends&gt;
+ &lt;depends&gt;util&lt;/depends&gt;
+ &lt;/package&gt;
+ &lt;/design&gt;
+</pre>
+<p>Notice in this example, if biz.xsoftware.dataaccess.XYZClass depended on biz.xsoftware.util.Util, the build would fail since that package dependency is not defined. Similarly, any class in biz.xsoftware.presentation cannot depend on any class in biz.xsoftware.dataaccess</p>
+<p>Also, notice that biz.xsoftware.presentation.Gui is allowed to depend on biz.xsoftware.util.pres.ClassInSubpackage because subpackages is set to include. This allows subpackages of biz.xsoftware.util to also be included in the design without having to define every subpackage.</p>
+<p>Lastly, notice the first line so javax and all javax subpackages can be depended on without declaring them. Use this sparingly though as sometimes you might want to isolate dependencies like depending on JMX to a certain package. For example, you may want only biz.xsoftware.management to depend on JMX and nothing else to depend on it. If you declare the same declaration I declared here for javax, you will not be able to guarantee that.</p>
+
+<h4>The wad design.xml file</h4>
+If you really want to, you could design for a wad. This is not suggested and if you want to do this, don't use this ant task please.
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;wad&quot; package=&quot;&lt;default package&gt;&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+
+<h4>Including subpackages design.xml</h4>
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;service1&quot; package=&quot;biz.xsoftware.service1&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;package name=&quot;client1&quot; package=&quot;biz.xsoftware.client1&quot; depends=&quot;service1&quot;/&gt;
+ &lt;package name=&quot;service2&quot; package=&quot;biz.xsoftware.service2&quot;/&gt;
+ &lt;package name=&quot;client2&quot; package=&quot;biz.xsoftware.client2&quot; depends=&quot;service2&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+<p>
+Note that here for service 1, classes in package biz.xsoftware.client1 can depend on any classes in biz.xsoftware.service1 and can also depend on classes in subpackages of biz.xsoftware.service1.
+</p>
+<p>
+Note that for service 2, classes in biz.xsoftware.client2 and client2's subpackages are all allowed to depend on classes in biz.xsoftware.service2.
+</p>
+<h4>One Design Note</h4>
+One big note to consider, there is one design dependency that verifydesign cannot see from the class file. This is due to the String constants(This only happens with static final <b>Strings</b> and static final <b>primitives</b> being compiled into the class file. Here is example code demonstrating this task cannot catch these dependencies....
+<pre>
+public class Client {
+ public void fakeMethod() {
+ String s = Dependency.CONSTANT; //verifydesign task can't tell this depends on
+ //DependencyClass as that info is lost after compiling
+ }
+}
+
+public class DependencyClass {
+ public static final String CONSTANT = "asdf";
+}
+</pre>
+
+<hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</body>
+</html>
+
diff --git a/docs/manual/tasks/verifylegacytutorial.html b/docs/manual/tasks/verifylegacytutorial.html
new file mode 100644
index 0000000..6999882
--- /dev/null
+++ b/docs/manual/tasks/verifylegacytutorial.html
@@ -0,0 +1,71 @@
+<html lang="en-us">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>VerifyDesign Legacy System Tutorial</title>
+</head>
+
+<body>
+
+<h2>VerifyDesign Legacy System Tutorial</h2>
+
+<p>If you have a legacy system, it can be overwhelming as a typical system is a mess when it comes to package dependencies. This tutorial shows a way to ease into the verifydesign task instead of fixing everything all at once.</p>
+
+<p>First, in your build.xml file, use this line to verify your jar(or you can modify it to verify multiple jars)</p>
+
+<pre>
+ &lt;verifydesign jar=&quot;yourjarname.jar&quot;
+ design=&quot;design.xml&quot;
+ /&gt;
+</pre>
+
+Now is the hardest part, go ahead and define every package and set the needDepends attribute to false for all of them so your design.xml should look like so
+
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;first&quot; package=&quot;your.first.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;second&quot; package=&quot;your.second.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;third&quot; package=&quot;your.third.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fourth&quot; package=&quot;your.fourth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fifth&quot; package=&quot;your.fifth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+
+Please give them better names then first, second, third, etc. You may have 100 packages on some projects and this may take a while to get started, but keep in mind once you are done with this, you are done with the majority of the work and the build will pass once you are done with this too!
+
+Now comes the fun part, learning about your design. Take a package that you want to start restricting dependencies on and erase the needDepends(by default it's value will be true). Let's take your.first.package and create the new design.xml file like so...
+
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;first&quot; package=&quot;your.first.package&quot;/&gt;
+ &lt;package name=&quot;second&quot; package=&quot;your.second.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;third&quot; package=&quot;your.third.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fourth&quot; package=&quot;your.fourth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fifth&quot; package=&quot;your.fifth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+
+Now we run the build and we get errors that your.first.package depends on second, third, and fourth. Let's pretend we only wanted to depend on second and third. We then change our design file to so...
+
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;first&quot; package=&quot;your.first.package&quot;
+ &lt;depends&gt;second&lt;/depends&gt;
+ &lt;depends&gt;third&lt;/depends&gt;
+ &lt;/package&gt;
+ &lt;package name=&quot;second&quot; package=&quot;your.second.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;third&quot; package=&quot;your.third.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fourth&quot; package=&quot;your.fourth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;package name=&quot;fifth&quot; package=&quot;your.fifth.package&quot; needDepends=&quot;false&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+
+Now we run the build and clean up all the code so that first doesn't depend on fourth anymore. This first step can typically take a full release if you are doing this in the margins. That is ok and now forever your.first.package will only depend on second and third until the design file is changed. You have made major progress. I would suggest a package a release. It can clean up dependencies and you will start finding it can be easier to add more and more features and not end up with a wad or mess on your hands. Good luck designing. Refactoring a legacy system can be very challenging and very long with or without this task. This ant task guarantees that you are actually heading in your defined direction. Whether the direction is correct or not is another story :).
+
+<hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</body>
+</html>
+
diff --git a/docs/manual/tasks/verifynewprojtutorial.html b/docs/manual/tasks/verifynewprojtutorial.html
new file mode 100644
index 0000000..96e066d
--- /dev/null
+++ b/docs/manual/tasks/verifynewprojtutorial.html
@@ -0,0 +1,39 @@
+<html lang="en-us">
+
+<head>
+<meta http-equiv="Content-Language" content="en-us">
+<title>VerifyDesign New Project Tutorial</title>
+</head>
+
+<body>
+
+<h2>VerifyDesign New Project Tutorial</h2>
+
+This is by far the easiest tutorial. Before you have any code, add this to your build.xml file.
+
+<pre>
+ &lt;verifydesign jar=&quot;yourjarname.jar&quot;
+ design=&quot;design.xml&quot;
+ /&gt;
+</pre>
+
+Create your design.xml file from the design that is in your head or in documentation like so
+
+<pre>
+ &lt;design&gt;
+ &lt;package name=&quot;service1&quot; package=&quot;biz.xsoftware.service1&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;package name=&quot;client1&quot; package=&quot;biz.xsoftware.client1&quot; depends=&quot;service1&quot;/&gt;
+ &lt;package name=&quot;service2&quot; package=&quot;biz.xsoftware.service2&quot;/&gt;
+ &lt;package name=&quot;client2&quot; package=&quot;biz.xsoftware.client2&quot; depends=&quot;service2&quot; subpackages=&quot;include&quot;/&gt;
+ &lt;/design&gt;
+</pre>
+
+From now on, when you run the build, if this is violated like service1 depending on client2 or something, the build will fail and you will catch the errors of violating the design before it is too late. You can then guarantee things like only this package will depend on the JMS technology. This way if you change JMS to something later, you know you only have to change that one package.
+
+<hr>
+ <p align="center">Copyright &copy; 2002-2004 Ant-Contrib Project. All
+ rights Reserved.</p>
+
+</body>
+</html>
+
diff --git a/ivy-conf.xml b/ivy-conf.xml
new file mode 100644
index 0000000..1929e5f
--- /dev/null
+++ b/ivy-conf.xml
@@ -0,0 +1,20 @@
+<ivy-conf>
+ <properties file="build.properties" />
+
+ <conf defaultResolver="default-resolver" checkUpToDate="true" />
+
+ <resolvers>
+ <filesystem name="local">
+ <ivy pattern="${ivy.conf.dir}/lib/[module]/ivy-[revision].xml" />
+ <artifact pattern="${ivy.conf.dir}/lib/[module]/[ext]s/[artifact]-[revision].[ext]" />
+ </filesystem>
+
+ <ivyrep name="ivyrep" />
+
+ <chain name="default-resolver">
+ <resolver ref="local" />
+ <resolver ref="ivyrep" />
+ </chain>
+ </resolvers>
+
+</ivy-conf> \ No newline at end of file
diff --git a/ivy.xml b/ivy.xml
new file mode 100644
index 0000000..cd37e8a
--- /dev/null
+++ b/ivy.xml
@@ -0,0 +1,27 @@
+<ivy-module version="1.1">
+ <info organisation="sourceforge" module="ant-contrib" />
+
+ <configurations>
+ <conf name="default" />
+ <conf name="test" extends="default" />
+ </configurations>
+ <publications>
+ <artifact name="ant-contrib" type="jar" />
+ </publications>
+
+ <dependencies>
+ <dependency org="apache"
+ name="bcel"
+ rev="5.1" />
+ <dependency org="apache"
+ name="ant"
+ rev="1.6.5" />
+ <dependency org="apache"
+ name="xercesImpl"
+ rev="2.6.2" />
+ <dependency org="junit"
+ name="junit"
+ rev="3.8.1"
+ conf="test->default" />
+ </dependencies>
+</ivy-module>
diff --git a/lib/ant/jars/ant-1.6.5.jar b/lib/ant/jars/ant-1.6.5.jar
new file mode 100644
index 0000000..3beb3b8
--- /dev/null
+++ b/lib/ant/jars/ant-1.6.5.jar
Binary files differ
diff --git a/lib/bcel/jars/bcel-5.1.jar b/lib/bcel/jars/bcel-5.1.jar
new file mode 100644
index 0000000..524e375
--- /dev/null
+++ b/lib/bcel/jars/bcel-5.1.jar
Binary files differ
diff --git a/lib/commons-cli/jars/commons-cli-1.0.jar b/lib/commons-cli/jars/commons-cli-1.0.jar
new file mode 100644
index 0000000..22a004e
--- /dev/null
+++ b/lib/commons-cli/jars/commons-cli-1.0.jar
Binary files differ
diff --git a/lib/commons-codec/jars/commons-codec-1.3.jar b/lib/commons-codec/jars/commons-codec-1.3.jar
new file mode 100644
index 0000000..67cb720
--- /dev/null
+++ b/lib/commons-codec/jars/commons-codec-1.3.jar
Binary files differ
diff --git a/lib/commons-httpclient/jars/commons-httpclient-3.0.1.jar b/lib/commons-httpclient/jars/commons-httpclient-3.0.1.jar
new file mode 100644
index 0000000..54a9300
--- /dev/null
+++ b/lib/commons-httpclient/jars/commons-httpclient-3.0.1.jar
Binary files differ
diff --git a/lib/commons-logging/jars/commons-logging-1.0.4.jar b/lib/commons-logging/jars/commons-logging-1.0.4.jar
new file mode 100644
index 0000000..b99c937
--- /dev/null
+++ b/lib/commons-logging/jars/commons-logging-1.0.4.jar
Binary files differ
diff --git a/lib/ivy/jars/ivy-1.3.1.jar b/lib/ivy/jars/ivy-1.3.1.jar
new file mode 100644
index 0000000..f860683
--- /dev/null
+++ b/lib/ivy/jars/ivy-1.3.1.jar
Binary files differ
diff --git a/lib/junit/jars/junit-3.8.1.jar b/lib/junit/jars/junit-3.8.1.jar
new file mode 100644
index 0000000..674d71e
--- /dev/null
+++ b/lib/junit/jars/junit-3.8.1.jar
Binary files differ
diff --git a/lib/oro/jars/oro-2.0.8.jar b/lib/oro/jars/oro-2.0.8.jar
new file mode 100644
index 0000000..23488d2
--- /dev/null
+++ b/lib/oro/jars/oro-2.0.8.jar
Binary files differ
diff --git a/lib/xercesImpl/jars/xercesImpl-2.6.2.jar b/lib/xercesImpl/jars/xercesImpl-2.6.2.jar
new file mode 100644
index 0000000..f0fb0e8
--- /dev/null
+++ b/lib/xercesImpl/jars/xercesImpl-2.6.2.jar
Binary files differ
diff --git a/src/java/net/sf/antcontrib/AntContribVersion.java b/src/java/net/sf/antcontrib/AntContribVersion.java
new file mode 100644
index 0000000..8633459
--- /dev/null
+++ b/src/java/net/sf/antcontrib/AntContribVersion.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib;
+
+/**
+ * @author Dean Hiller
+ *
+ * To change the template for this generated type comment go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+public class AntContribVersion {
+
+ private Package thePackage;
+
+ /**
+ * The main program for MockVersion that prints the version info from
+ * the manifest file.
+ *
+ * @param args Ignores all arguments.
+ */
+ public static void main(String[] args) {
+ AntContribVersion version = new AntContribVersion(AntContribVersion.class);
+ System.out.println(""+version);
+ }
+
+ /**
+ * Constructor that takes a class to get the version information
+ * from out of the manifest. Uses the class's package to retrieve
+ * the manifest version info.
+ * @param c The Class on whose package to use to get version info.
+ */
+ public AntContribVersion(Class c) {
+ String name = c.getName();
+ int index = name.lastIndexOf(".");
+
+ if(index < 0)
+ throw new RuntimeException("This class is the default package and can't be to use this feature");
+
+ String packageName = name.substring(0, index);
+ thePackage = Package.getPackage(packageName);
+ }
+
+
+ /**
+ * Prints the version info the MockVersion represents.
+ *
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ String version = "\nVersion of Ant Contrib...";
+ version += "\ntitle="+thePackage.getImplementationTitle();
+ version += "\nwebsite="+thePackage.getImplementationVendor();
+ version += "\nversion="+thePackage.getImplementationVersion()+"\n";
+
+ return version;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antclipse/ClassPathParser.java b/src/java/net/sf/antcontrib/antclipse/ClassPathParser.java
new file mode 100644
index 0000000..389c89e
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antclipse/ClassPathParser.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antclipse;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Classic tool firing a SAX parser. Must feed the source file and a handler.
+ * Nothing really special about it, only probably some special file handling in nasty cases
+ * (Windows files containing strange chars, internationalized filenames,
+ * but you shouldn't be doing this, anyway :)).
+ * @author Adrian Spinei [email protected]
+ * @version $Revision: 1.2 $
+ * @since Ant 1.5
+ */
+public class ClassPathParser
+{
+ void parse(File file, HandlerBase handler) throws BuildException
+ {
+ String fName = file.getName();
+ FileInputStream fileInputStream = null;
+ InputSource inputSource = null;
+ try
+ {
+ SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
+ //go to UFS if we're on win
+ String uri = "file:" + fName.replace('\\', '/');
+ fileInputStream = new FileInputStream(file);
+ inputSource = new InputSource(fileInputStream);
+ inputSource.setSystemId(uri);
+ saxParser.parse(inputSource, handler);
+ }
+ catch (ParserConfigurationException pceException)
+ {
+ throw new BuildException("Parser configuration failed", pceException);
+ }
+ catch (SAXParseException exc)
+ {
+ Location location = new Location(fName.toString(), exc.getLineNumber(), exc.getColumnNumber());
+ Throwable throwable = exc.getException();
+ if ((Object) throwable instanceof BuildException)
+ {
+ BuildException be = (BuildException) (Object) throwable;
+ if (be.getLocation() == Location.UNKNOWN_LOCATION)
+ be.setLocation(location);
+ throw be;
+ }
+ throw new BuildException(exc.getMessage(), throwable, location);
+ }
+ catch (SAXException exc)
+ {
+ Throwable throwable = exc.getException();
+ if ((Object) throwable instanceof BuildException)
+ throw (BuildException) (Object) throwable;
+ throw new BuildException(exc.getMessage(), throwable);
+ }
+ catch (FileNotFoundException exc)
+ {
+ throw new BuildException(exc);
+ }
+ catch (IOException exc)
+ {
+ throw new BuildException("Error reading file", exc);
+ }
+ finally
+ {
+ if (fileInputStream != null)
+ {
+ try
+ {
+ fileInputStream.close();
+ }
+ catch (IOException ioexception)
+ {
+ //do nothing, should not appear
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antclipse/ClassPathTask.java b/src/java/net/sf/antcontrib/antclipse/ClassPathTask.java
new file mode 100644
index 0000000..6c32181
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antclipse/ClassPathTask.java
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antclipse;
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Path.PathElement;
+import org.apache.tools.ant.util.RegexpPatternMapper;
+import org.xml.sax.AttributeList;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ * Support class for the Antclipse task. Basically, it takes the .classpath Eclipse file
+ * and feeds a SAX parser. The handler is slightly different according to what we want to
+ * obtain (a classpath or a fileset)
+ * @author Adrian Spinei [email protected]
+ * @version $Revision: 1.2 $
+ * @since Ant 1.5
+ */
+public class ClassPathTask extends Task
+{
+ private String project;
+ private String idContainer = "antclipse";
+ private boolean includeSource = false; //default, do not include source
+ private boolean includeOutput = false; //default, do not include output directory
+ private boolean includeLibs = true; //default, include all libraries
+ private boolean verbose = false; //default quiet
+ RegexpPatternMapper irpm = null;
+ RegexpPatternMapper erpm = null;
+ public static final String TARGET_CLASSPATH = "classpath";
+ public static final String TARGET_FILESET = "fileset";
+ private String produce = null; //classpath by default
+
+ /**
+ * Setter for task parameter
+ * @param includeLibs Boolean, whether to include or not the project libraries. Default is true.
+ */
+ public void setIncludeLibs(boolean includeLibs)
+ {
+ this.includeLibs = includeLibs;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param produce This parameter tells the task wether to produce a "classpath" or a "fileset" (multiple filesets, as a matter of fact).
+ */
+ public void setproduce(String produce)
+ {
+ this.produce = produce;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param verbose Boolean, telling the app to throw some info during each step. Default is false.
+ */
+ public void setVerbose(boolean verbose)
+ {
+ this.verbose = verbose;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param excludes A regexp for files to exclude. It is taken into account only when producing a classpath, doesn't work on source or output files. It is a real regexp, not a "*" expression.
+ */
+ public void setExcludes(String excludes)
+ {
+ if (excludes != null)
+ {
+ erpm = new RegexpPatternMapper();
+ erpm.setFrom(excludes);
+ erpm.setTo("."); //mandatory
+ }
+ else
+ erpm = null;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param includes A regexp for files to include. It is taken into account only when producing a classpath, doesn't work on source or output files. It is a real regexp, not a "*" expression.
+ */
+ public void setIncludes(String includes)
+ {
+ if (includes != null)
+ {
+ irpm = new RegexpPatternMapper();
+ irpm.setFrom(includes);
+ irpm.setTo("."); //mandatory
+ }
+ else
+ irpm = null;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param idContainer The refid which will serve to identify the deliverables. When multiple filesets are produces, their refid is a concatenation between this value and something else (usually obtained from a path). Default "antclipse"
+ */
+ public void setIdContainer(String idContainer)
+ {
+ this.idContainer = idContainer;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param includeOutput Boolean, whether to include or not the project output directories. Default is false.
+ */
+ public void setIncludeOutput(boolean includeOutput)
+ {
+ this.includeOutput = includeOutput;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param includeSource Boolean, whether to include or not the project source directories. Default is false.
+ */
+ public void setIncludeSource(boolean includeSource)
+ {
+ this.includeSource = includeSource;
+ }
+
+ /**
+ * Setter for task parameter
+ * @param project project name
+ */
+ public void setProject(String project)
+ {
+ this.project = project;
+ }
+
+ /**
+ * @see org.apache.tools.ant.Task#execute()
+ */
+ public void execute() throws BuildException
+ {
+ if (!TARGET_CLASSPATH.equalsIgnoreCase(this.produce) && !TARGET_FILESET.equals(this.produce))
+ throw new BuildException(
+ "Mandatory target must be either '" + TARGET_CLASSPATH + "' or '" + TARGET_FILESET + "'");
+ ClassPathParser parser = new ClassPathParser();
+ AbstractCustomHandler handler;
+ if (TARGET_CLASSPATH.equalsIgnoreCase(this.produce))
+ {
+ Path path = new Path(this.getProject());
+ this.getProject().addReference(this.idContainer, path);
+ handler = new PathCustomHandler(path);
+ }
+ else
+ {
+ FileSet fileSet = new FileSet();
+ this.getProject().addReference(this.idContainer, fileSet);
+ fileSet.setDir(new File(this.getProject().getBaseDir().getAbsolutePath().toString()));
+ handler = new FileSetCustomHandler(fileSet);
+ }
+ parser.parse(new File(this.getProject().getBaseDir().getAbsolutePath(), ".classpath"), handler);
+ }
+
+ abstract class AbstractCustomHandler extends HandlerBase
+ {
+ protected String projDir;
+ protected static final String ATTRNAME_PATH = "path";
+ protected static final String ATTRNAME_KIND = "kind";
+ protected static final String ATTR_LIB = "lib";
+ protected static final String ATTR_SRC = "src";
+ protected static final String ATTR_OUTPUT = "output";
+ protected static final String EMPTY = "";
+ }
+
+ class FileSetCustomHandler extends AbstractCustomHandler
+ {
+ private FileSet fileSet = null;
+
+ /**
+ * nazi style, forbid default constructor
+ */
+ private FileSetCustomHandler()
+ {
+ }
+
+ /**
+ * @param fileSet
+ */
+ public FileSetCustomHandler(FileSet fileSet)
+ {
+ super();
+ this.fileSet = fileSet;
+ projDir = getProject().getBaseDir().getAbsolutePath().toString();
+ }
+
+ /**
+ * @see org.xml.sax.DocumentHandler#endDocument()
+ */
+ public void endDocument() throws SAXException
+ {
+ super.endDocument();
+ if (fileSet != null && !fileSet.hasPatterns())
+ fileSet.setExcludes("**/*");
+ //exclude everything or we'll take all the project dirs
+ }
+
+ public void startElement(String tag, AttributeList attrs) throws SAXParseException
+ {
+ if (tag.equalsIgnoreCase("classpathentry"))
+ {
+ //start by checking if the classpath is coherent at all
+ String kind = attrs.getValue(ATTRNAME_KIND);
+ if (kind == null)
+ throw new BuildException("classpathentry 'kind' attribute is mandatory");
+ String path = attrs.getValue(ATTRNAME_PATH);
+ if (path == null)
+ throw new BuildException("classpathentry 'path' attribute is mandatory");
+
+ //put the outputdirectory in a property
+ if (kind.equalsIgnoreCase(ATTR_OUTPUT))
+ {
+ String propName = idContainer + "outpath";
+ Property property = new Property();
+ property.setName(propName);
+ property.setValue(path);
+ property.setProject(getProject());
+ property.execute();
+ if (verbose)
+ System.out.println("Setting property " + propName + " to value " + path);
+ }
+
+ //let's put the last source directory in a property
+ if (kind.equalsIgnoreCase(ATTR_SRC))
+ {
+ String propName = idContainer + "srcpath";
+ Property property = new Property();
+ property.setName(propName);
+ property.setValue(path);
+ property.setProject(getProject());
+ property.execute();
+ if (verbose)
+ System.out.println("Setting property " + propName + " to value " + path);
+ }
+
+ if ((kind.equalsIgnoreCase(ATTR_SRC) && includeSource)
+ || (kind.equalsIgnoreCase(ATTR_OUTPUT) && includeOutput)
+ || (kind.equalsIgnoreCase(ATTR_LIB) && includeLibs))
+ {
+ //all seem fine
+ // check the includes
+ String[] inclResult = new String[] { "all included" };
+ if (irpm != null)
+ {
+ inclResult = irpm.mapFileName(path);
+ }
+ String[] exclResult = null;
+ if (erpm != null)
+ {
+ exclResult = erpm.mapFileName(path);
+ }
+ if (inclResult != null && exclResult == null)
+ {
+ //THIS is the specific code
+ if (kind.equalsIgnoreCase(ATTR_OUTPUT))
+ {
+ //we have included output so let's build a new fileset
+ FileSet outFileSet = new FileSet();
+ String newReference = idContainer + "-" + path.replace(File.separatorChar, '-');
+ getProject().addReference(newReference, outFileSet);
+ if (verbose)
+ System.out.println(
+ "Created new fileset "
+ + newReference
+ + " containing all the files from the output dir "
+ + projDir
+ + File.separator
+ + path);
+ outFileSet.setDefaultexcludes(false);
+ outFileSet.setDir(new File(projDir + File.separator + path));
+ outFileSet.setIncludes("**/*"); //get everything
+ }
+ else
+ if (kind.equalsIgnoreCase(ATTR_SRC))
+ {
+ //we have included source so let's build a new fileset
+ FileSet srcFileSet = new FileSet();
+ String newReference = idContainer + "-" + path.replace(File.separatorChar, '-');
+ getProject().addReference(newReference, srcFileSet);
+ if (verbose)
+ System.out.println(
+ "Created new fileset "
+ + newReference
+ + " containing all the files from the source dir "
+ + projDir
+ + File.separator
+ + path);
+ srcFileSet.setDefaultexcludes(false);
+ srcFileSet.setDir(new File(projDir + File.separator + path));
+ srcFileSet.setIncludes("**/*"); //get everything
+ }
+ else
+ {
+ //not otuptut, just add file after file to the fileset
+ File file = new File(fileSet.getDir(getProject()) + "/" + path);
+ if (file.isDirectory())
+ path += "/**/*";
+ if (verbose)
+ System.out.println(
+ "Adding "
+ + path
+ + " to fileset "
+ + idContainer
+ + " at "
+ + fileSet.getDir(getProject()));
+ fileSet.setIncludes(path);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ class PathCustomHandler extends AbstractCustomHandler
+ {
+ private Path path = null;
+
+ /**
+ * @param path the path to add files
+ */
+ public PathCustomHandler(Path path)
+ {
+ super();
+ this.path = path;
+ }
+
+ /**
+ * nazi style, forbid default constructor
+ */
+ private PathCustomHandler()
+ {
+ }
+
+ public void startElement(String tag, AttributeList attrs) throws SAXParseException
+ {
+ if (tag.equalsIgnoreCase("classpathentry"))
+ {
+ //start by checking if the classpath is coherent at all
+ String kind = attrs.getValue(ATTRNAME_KIND);
+ if (kind == null)
+ throw new BuildException("classpathentry 'kind' attribute is mandatory");
+ String path = attrs.getValue(ATTRNAME_PATH);
+ if (path == null)
+ throw new BuildException("classpathentry 'path' attribute is mandatory");
+
+ //put the outputdirectory in a property
+ if (kind.equalsIgnoreCase(ATTR_OUTPUT))
+ {
+ String propName = idContainer + "outpath";
+ Property property = new Property();
+ property.setName(propName);
+ property.setValue(path);
+ property.setProject(getProject());
+ property.execute();
+ if (verbose)
+ System.out.println("Setting property " + propName + " to value " + path);
+ }
+
+ //let's put the last source directory in a property
+ if (kind.equalsIgnoreCase(ATTR_SRC))
+ {
+ String propName = idContainer + "srcpath";
+ Property property = new Property();
+ property.setName(propName);
+ property.setValue(path);
+ property.setProject(getProject());
+ property.execute();
+ if (verbose)
+ System.out.println("Setting property " + propName + " to value " + path);
+ }
+
+ if ((kind.equalsIgnoreCase(ATTR_SRC) && includeSource)
+ || (kind.equalsIgnoreCase(ATTR_OUTPUT) && includeOutput)
+ || (kind.equalsIgnoreCase(ATTR_LIB) && includeLibs))
+ {
+ //all seem fine
+ // check the includes
+ String[] inclResult = new String[] { "all included" };
+ if (irpm != null)
+ {
+ inclResult = irpm.mapFileName(path);
+ }
+ String[] exclResult = null;
+ if (erpm != null)
+ {
+ exclResult = erpm.mapFileName(path);
+ }
+ if (inclResult != null && exclResult == null)
+ {
+ //THIS is the only specific code
+ if (verbose)
+ System.out.println("Adding " + path + " to classpath " + idContainer);
+ PathElement element = this.path.createPathElement();
+ element.setLocation(new File(path));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antcontrib.properties b/src/java/net/sf/antcontrib/antcontrib.properties
new file mode 100644
index 0000000..3ddba23
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antcontrib.properties
@@ -0,0 +1,55 @@
+
+# Antclipse tasks
+antclipse=net.sf.antcontrib.antclipse.ClassPathTask
+
+# AntServer tasks
+antserver=net.sf.antcontrib.antserver.server.ServerTask
+remoteant=net.sf.antcontrib.antserver.client.ClientTask
+
+# Design Tasks
+verifydesign=net.sf.antcontrib.design.VerifyDesign
+
+# IniFile
+inifile=net.sf.antcontrib.inifile.IniFileTask
+
+# Logic tasks
+if=net.sf.antcontrib.logic.IfTask
+foreach=net.sf.antcontrib.logic.ForEach
+throw=net.sf.antcontrib.logic.Throw
+trycatch=net.sf.antcontrib.logic.TryCatchTask
+switch=net.sf.antcontrib.logic.Switch
+outofdate=net.sf.antcontrib.logic.OutOfDate
+runtarget=net.sf.antcontrib.logic.RunTargetTask
+timestampselector=net.sf.antcontrib.logic.TimestampSelector
+antcallback=net.sf.antcontrib.logic.AntCallBack
+antfetch=net.sf.antcontrib.logic.AntFetch
+assert=net.sf.antcontrib.logic.Assert
+
+# Math Tasks
+math=net.sf.antcontrib.math.MathTask
+
+# Net tasks
+post=net.sf.antcontrib.net.PostTask
+
+# Peformance Tasks
+stopwatch=net.sf.antcontrib.perf.StopWatchTask
+
+# Platform Tasks
+osfamily=net.sf.antcontrib.platform.OsFamily
+shellscript=net.sf.antcontrib.platform.ShellScriptTask
+
+# Process Tasks
+forget=net.sf.antcontrib.process.ForgetTask
+limit=net.sf.antcontrib.process.Limit
+
+# Property Tasks
+propertycopy=net.sf.antcontrib.property.PropertyCopy
+pathtofileset=net.sf.antcontrib.property.PathToFileSet
+propertyselector=net.sf.antcontrib.property.PropertySelector
+propertyregex=net.sf.antcontrib.property.RegexTask
+sortlist=net.sf.antcontrib.property.SortList
+urlencode=net.sf.antcontrib.property.URLEncodeTask
+var=net.sf.antcontrib.property.Variable
+
+# Walls Tasks
+compilewithwalls=net.sf.antcontrib.walls.CompileWithWalls
diff --git a/src/java/net/sf/antcontrib/antlib.xml b/src/java/net/sf/antcontrib/antlib.xml
new file mode 100644
index 0000000..69cfa43
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antlib.xml
@@ -0,0 +1,9 @@
+<antlib>
+ <!-- typedef the tasks that work for ant less than 1.6 -->
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
+
+ <taskdef
+ name="for"
+ classname="net.sf.antcontrib.logic.ForTask"
+ onerror="report"/>
+</antlib>
diff --git a/src/java/net/sf/antcontrib/antserver/Command.java b/src/java/net/sf/antcontrib/antserver/Command.java
new file mode 100644
index 0000000..e9d84a0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/Command.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+
+import org.apache.tools.ant.Project;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public interface Command
+ extends Serializable
+{
+ /***
+ * This should throw a build exception if the parameters
+ * are invalid.
+ */
+ public void validate(Project project);
+
+ /***
+ * Is there additional content being sent from the local
+ * machine to the remote server
+ */
+ public long getContentLength();
+
+ /***
+ * Gets the content's input stream. Should be called only on the
+ * client side for sending the content over the connection
+ * @return the content's input stream.
+ */
+ public InputStream getContentStream() throws IOException;
+
+
+ public long getResponseContentLength();
+
+ public InputStream getReponseContentStream() throws IOException;
+
+ /***
+ * Execute the command.
+ * @param project The project which is being executed
+ * @return If true, the connection will be closed
+ * @throws Throwable
+ */
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws Throwable;
+
+ /***
+ * Process any additional data from a response.
+ */
+ public boolean respond(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws IOException;
+
+}
diff --git a/src/java/net/sf/antcontrib/antserver/Response.java b/src/java/net/sf/antcontrib/antserver/Response.java
new file mode 100644
index 0000000..b1958d9
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/Response.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class Response
+ implements Serializable
+{
+ private boolean succeeded;
+ private String errorStackTrace;
+ private String errorMessage;
+ private String resultsXml;
+
+ private long contentLength;
+
+ public Response()
+ {
+ super();
+ this.succeeded = true;
+ }
+
+
+ public boolean isSucceeded()
+ {
+ return succeeded;
+ }
+
+
+ public void setSucceeded(boolean succeeded)
+ {
+ this.succeeded = succeeded;
+ }
+
+ public void setThrowable(Throwable t)
+ {
+ errorMessage = t.getMessage();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ setErrorStackTrace(baos.toString());
+ }
+
+ public String getErrorStackTrace()
+ {
+ return errorStackTrace;
+ }
+
+
+ public void setErrorStackTrace(String errorStackTrace)
+ {
+ this.errorStackTrace = errorStackTrace;
+ }
+
+
+ public String getErrorMessage()
+ {
+ return errorMessage;
+ }
+
+
+ public void setErrorMessage(String errorMessage)
+ {
+ this.errorMessage = errorMessage;
+ }
+
+
+ public String getResultsXml()
+ {
+ return resultsXml;
+ }
+
+
+ public void setResultsXml(String resultsXml)
+ {
+ this.resultsXml = resultsXml;
+ }
+
+ public long getContentLength()
+ {
+ return contentLength;
+ }
+
+ public void setContentLength(long contentLength)
+ {
+ this.contentLength = contentLength;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/Util.java b/src/java/net/sf/antcontrib/antserver/Util.java
new file mode 100644
index 0000000..124e315
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/Util.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Util
+{
+ public static final int CHUNK = 10*1024;
+
+ public static final void transferBytes(InputStream input,
+ long length,
+ OutputStream output,
+ boolean closeInput)
+ throws IOException
+ {
+
+ byte b[] = new byte[CHUNK];
+ int read = 0;
+ int totalread = 0;
+
+ while (totalread < length)
+ {
+ int toRead = (int)Math.min(CHUNK, length - totalread);
+ read = input.read(b, 0, toRead);
+ output.write(b, 0, read);
+ totalread += read;
+ }
+
+ try
+ {
+ if (closeInput)
+ input.close();
+ }
+ catch (IOException e)
+ {
+ // ; gulp
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/client/Client.java b/src/java/net/sf/antcontrib/antserver/client/Client.java
new file mode 100644
index 0000000..061815f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/client/Client.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antserver.client;
+
+import java.io.*;
+import java.net.Socket;
+import java.net.SocketException;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.Util;
+import net.sf.antcontrib.antserver.commands.DisconnectCommand;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Client
+{
+ private String machine;
+ private int port;
+ private Project project;
+
+
+ public Client(Project project, String machine, int port)
+ {
+ super();
+ this.machine = machine;
+ this.port = port;
+ this.project = project;
+ }
+
+
+ private Socket socket;
+ private OutputStream os;
+ private InputStream is;
+ private ObjectOutputStream oos;
+ private ObjectInputStream ois;
+ private boolean connected;
+
+
+ public void connect()
+ throws IOException
+ {
+ project.log("Opening connection to " + machine + ":" + port,
+ Project.MSG_DEBUG);
+
+ try
+ {
+ socket = new Socket(machine, port);
+ socket.setKeepAlive(true);
+ project.log("Got connection to " + machine + ":" + port,
+ Project.MSG_DEBUG);
+
+ os = socket.getOutputStream();
+ is = socket.getInputStream();
+
+ oos = new ObjectOutputStream(os);
+ ois = new ObjectInputStream(is);
+
+ connected = true;
+ try
+ {
+ // Read the initial response object so that the
+ // object stream is initialized
+ ois.readObject();
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+ }
+ finally
+ {
+ // If we were unable to connect, close everything
+ if (!connected)
+ {
+
+ try
+ {
+ if (os != null)
+ os.close();
+ os = null;
+ oos = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+
+ try
+ {
+ if (is != null)
+ is.close();
+ is = null;
+ ois = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+
+ try
+ {
+ if (socket != null)
+ socket.close();
+ socket = null;
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+ }
+
+
+ }
+
+ public void shutdown()
+ {
+ try
+ {
+ if (os != null)
+ os.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+
+ }
+ os = null;
+ oos = null;
+
+ try
+ {
+ if (is != null)
+ is.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+
+ }
+ is = null;
+ ois = null;
+
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ socket = null;
+
+ connected = false;
+ }
+
+
+ public void disconnect()
+ throws IOException
+ {
+ if (!connected)
+ return;
+
+ try {
+ oos.writeObject(DisconnectCommand.DISCONNECT_COMMAND);
+ try
+ {
+ // Read disconnect response
+ ois.readObject();
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+
+ shutdown();
+ }
+ catch (SocketException e) {
+ ; // connection was closed
+ }
+ catch (EOFException e) {
+ ; // connection was closed
+ }
+ }
+
+
+ public Response sendCommand(Command command)
+ throws IOException
+ {
+ project.log("Sending command: " + command,
+ Project.MSG_DEBUG);
+ oos.writeObject(command);
+
+ if (command.getContentLength() > 0)
+ {
+ Util.transferBytes(command.getContentStream(),
+ command.getContentLength(),
+ os,
+ true);
+ }
+
+ Response response = null;
+
+ try
+ {
+ // Read the response object
+ response = (Response) ois.readObject();
+ project.log("Received Response: " + response,
+ Project.MSG_DEBUG);
+ if (response.getContentLength() != 0)
+ {
+ command.respond(project,
+ response.getContentLength(),
+ is);
+ }
+ }
+ catch (ClassNotFoundException e)
+ {
+ ; // gulp
+ }
+
+ return response;
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/antserver/client/ClientTask.java b/src/java/net/sf/antcontrib/antserver/client/ClientTask.java
new file mode 100644
index 0000000..34236f0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/client/ClientTask.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.client;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.Vector;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.commands.RunAntCommand;
+import net.sf.antcontrib.antserver.commands.RunTargetCommand;
+import net.sf.antcontrib.antserver.commands.SendFileCommand;
+import net.sf.antcontrib.antserver.commands.ShutdownCommand;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ClientTask
+ extends Task
+{
+ private String machine = "localhost";
+ private int port = 17000;
+ private Vector commands;
+ private boolean persistant = false;
+ private boolean failOnError = true;
+
+ public ClientTask()
+ {
+ super();
+ this.commands = new Vector();
+ }
+
+
+ public void setMachine(String machine)
+ {
+ this.machine = machine;
+ }
+
+
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+
+ public void setPersistant(boolean persistant)
+ {
+ this.persistant = persistant;
+ }
+
+
+ public void setFailOnError(boolean failOnError)
+ {
+ this.failOnError = failOnError;
+ }
+
+
+ public void addConfiguredShutdown(ShutdownCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredRunTarget(RunTargetCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredRunAnt(RunAntCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+ public void addConfiguredSendFile(SendFileCommand cmd)
+ {
+ commands.add(cmd);
+ }
+
+
+ public void execute()
+ {
+ Enumeration e = commands.elements();
+ Command c = null;
+ while (e.hasMoreElements())
+ {
+ c = (Command)e.nextElement();
+ c.validate(getProject());
+ }
+
+ Client client = new Client(getProject(), machine, port);
+
+ try
+ {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ try
+ {
+ int failCount = 0;
+
+ client.connect();
+
+ e = commands.elements();
+ c = null;
+ Response r = null;
+ Document d = null;
+ boolean keepGoing = true;
+ while (e.hasMoreElements() && keepGoing)
+ {
+ c = (Command)e.nextElement();
+ r = client.sendCommand(c);
+ if (! r.isSucceeded())
+ {
+ failCount++;
+ log("Command caused a build failure:" + c,
+ Project.MSG_ERR);
+ log(r.getErrorMessage(),
+ Project.MSG_ERR);
+ log(r.getErrorStackTrace(),
+ Project.MSG_DEBUG);
+ if (! persistant)
+ keepGoing = false;
+ }
+
+ try
+ {
+ ByteArrayInputStream bais =
+ new ByteArrayInputStream(r.getResultsXml().getBytes());
+ d = db.parse(bais);
+ NodeList nl = d.getElementsByTagName("target");
+ int len = nl.getLength();
+ Element element = null;
+ for (int i=0;i<len;i++)
+ {
+ element = (Element)nl.item(i);
+ getProject().log("[" + element.getAttribute("name") + "]",
+ Project.MSG_INFO);
+ }
+ }
+ catch (SAXException se)
+ {
+
+ }
+
+ if (c instanceof ShutdownCommand)
+ {
+ keepGoing = false;
+ client.shutdown();
+ }
+ }
+
+ if (failCount > 0 && failOnError)
+ throw new BuildException("One or more commands failed.");
+ }
+ finally
+ {
+ if (client != null)
+ client.disconnect();
+ }
+ }
+ catch (ParserConfigurationException ex)
+ {
+ throw new BuildException(ex);
+ }
+ catch (IOException ex)
+ {
+ throw new BuildException(ex);
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java b/src/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java
new file mode 100644
index 0000000..9734631
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/AbstractCommand.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antserver.commands;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public abstract class AbstractCommand
+ implements Command
+{
+ public long getContentLength()
+ {
+ return 0;
+ }
+
+
+ public InputStream getContentStream()
+ throws IOException
+ {
+ return null;
+ }
+
+
+ public long getResponseContentLength()
+ {
+ return 0;
+ }
+
+
+ public InputStream getReponseContentStream() throws IOException
+ {
+ return null;
+ }
+
+
+ public boolean respond(Project project,
+ long contentLength,
+ InputStream contentStream)
+ throws IOException
+ {
+ return false;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java b/src/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java
new file mode 100644
index 0000000..a89177b
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/DisconnectCommand.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class DisconnectCommand
+ extends AbstractCommand
+ implements Command
+{
+ public static Command DISCONNECT_COMMAND =
+ new DisconnectCommand();
+
+ private DisconnectCommand()
+ {
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ return true;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java b/src/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java
new file mode 100644
index 0000000..68f884f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/HelloWorldCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class HelloWorldCommand
+ extends AbstractCommand
+ implements Command
+{
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ project.log("Hello World", Project.MSG_ERR);
+ return false;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java b/src/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java
new file mode 100644
index 0000000..9c7aaf4
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/PropertyContainer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class PropertyContainer
+ implements Serializable
+{
+ private String name;
+ private String value;
+
+ public PropertyContainer()
+ {
+ super();
+ }
+
+
+ public String getName()
+ {
+ return name;
+ }
+
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ public String getValue()
+ {
+ return value;
+ }
+
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java b/src/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java
new file mode 100644
index 0000000..e755343
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/ReferenceContainer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.Serializable;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ReferenceContainer
+ implements Serializable
+{
+ private String refId;
+ private String toRefId;
+
+ public ReferenceContainer()
+ {
+ super();
+ }
+
+
+ public String getRefId()
+ {
+ return refId;
+ }
+
+
+ public void setRefid(String refId)
+ {
+ this.refId = refId;
+ }
+
+
+ public String getToRefId()
+ {
+ return toRefId;
+ }
+
+
+ public void setToRefId(String toRefId)
+ {
+ this.toRefId = toRefId;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java b/src/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java
new file mode 100644
index 0000000..51b114c
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/RunAntCommand.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.Property;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class RunAntCommand
+ extends AbstractCommand
+ implements Command
+{
+
+ private String antFile;
+ private String dir;
+ private String target;
+ private Vector properties;
+ private Vector references;
+ private boolean inheritall = false;
+ private boolean interitrefs = false;
+
+ public RunAntCommand()
+ {
+ super();
+ this.properties = new Vector();
+ this.references = new Vector();
+ }
+
+
+ public String getTarget()
+ {
+ return target;
+ }
+
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+
+ public Vector getProperties()
+ {
+ return properties;
+ }
+
+
+ public void setProperties(Vector properties)
+ {
+ this.properties = properties;
+ }
+
+ public Vector getReferences()
+ {
+ return references;
+ }
+
+
+ public void setReferences(Vector references)
+ {
+ this.references = references;
+ }
+
+ public boolean isInheritall()
+ {
+ return inheritall;
+ }
+
+
+ public void setInheritall(boolean inheritall)
+ {
+ this.inheritall = inheritall;
+ }
+
+
+ public boolean isInteritrefs()
+ {
+ return interitrefs;
+ }
+
+
+ public void setInteritrefs(boolean interitrefs)
+ {
+ this.interitrefs = interitrefs;
+ }
+
+
+ public String getAntFile()
+ {
+ return antFile;
+ }
+
+
+ public void setAntFile(String antFile)
+ {
+ this.antFile = antFile;
+ }
+
+
+ public String getDir()
+ {
+ return dir;
+ }
+
+
+ public void setDir(String dir)
+ {
+ this.dir = dir;
+ }
+
+
+ public void addConfiguredProperty(PropertyContainer property)
+ {
+ properties.addElement(property);
+ }
+
+ public void addConfiguredReference(ReferenceContainer reference)
+ {
+ references.addElement(reference);
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ Ant ant = (Ant)project.createTask("ant");
+ File baseDir = project.getBaseDir();
+ if (dir != null)
+ baseDir = new File(dir);
+ ant.setDir(baseDir);
+ ant.setInheritAll(inheritall);
+ ant.setInheritRefs(interitrefs);
+
+ if (target != null)
+ ant.setTarget(target);
+
+ if (antFile != null)
+ ant.setAntfile(antFile);
+
+ Enumeration e = properties.elements();
+ PropertyContainer pc = null;
+ Property p = null;
+ while (e.hasMoreElements())
+ {
+ pc = (PropertyContainer)e.nextElement();
+ p = ant.createProperty();
+ p.setName(pc.getName());
+ p.setValue(pc.getValue());
+ }
+
+ e = references.elements();
+ ReferenceContainer rc = null;
+ Ant.Reference ref = null;
+ while (e.hasMoreElements())
+ {
+ rc = (ReferenceContainer)e.nextElement();
+ ref = new Ant.Reference();
+ ref.setRefId(rc.getRefId());
+ ref.setToRefid(rc.getToRefId());
+ ant.addReference(ref);
+ }
+
+ ant.execute();
+
+ return false;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java b/src/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java
new file mode 100644
index 0000000..a22e5db
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/RunTargetCommand.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.CallTarget;
+import org.apache.tools.ant.taskdefs.Property;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class RunTargetCommand
+ extends AbstractCommand
+ implements Command
+{
+ private String target;
+ private Vector properties;
+ private Vector references;
+ private boolean inheritall = false;
+ private boolean interitrefs = false;
+
+ public RunTargetCommand()
+ {
+ super();
+ this.properties = new Vector();
+ this.references = new Vector();
+ }
+
+
+ public String getTarget()
+ {
+ return target;
+ }
+
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+
+ public Vector getProperties()
+ {
+ return properties;
+ }
+
+
+ public void setProperties(Vector properties)
+ {
+ this.properties = properties;
+ }
+
+
+
+ public Vector getReferences()
+ {
+ return references;
+ }
+
+
+ public void setReferences(Vector references)
+ {
+ this.references = references;
+ }
+
+
+ public boolean isInheritall()
+ {
+ return inheritall;
+ }
+
+
+ public void setInheritall(boolean inheritall)
+ {
+ this.inheritall = inheritall;
+ }
+
+
+ public boolean isInteritrefs()
+ {
+ return interitrefs;
+ }
+
+
+ public void setInteritrefs(boolean interitrefs)
+ {
+ this.interitrefs = interitrefs;
+ }
+
+
+ public void addConfiguredProperty(PropertyContainer property)
+ {
+ properties.addElement(property);
+ }
+
+
+ public void addConfiguredReference(ReferenceContainer reference)
+ {
+ references.addElement(reference);
+ }
+
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ CallTarget callTarget = (CallTarget)project.createTask("antcall");
+ callTarget.setInheritAll(inheritall);
+ callTarget.setInheritRefs(interitrefs);
+
+ String toExecute = target;
+ if (toExecute == null)
+ toExecute = project.getDefaultTarget();
+ callTarget.setTarget(toExecute);
+
+ Enumeration e = properties.elements();
+ PropertyContainer pc = null;
+ Property p = null;
+ while (e.hasMoreElements())
+ {
+ pc = (PropertyContainer)e.nextElement();
+ p = callTarget.createParam();
+ p.setName(pc.getName());
+ p.setValue(pc.getValue());
+ }
+
+
+ e = references.elements();
+ ReferenceContainer rc = null;
+ Ant.Reference ref = null;
+ while (e.hasMoreElements())
+ {
+ rc = (ReferenceContainer)e.nextElement();
+ ref = new Ant.Reference();
+ ref.setRefId(rc.getRefId());
+ ref.setToRefid(rc.getToRefId());
+ callTarget.addReference(ref);
+ }
+
+ callTarget.execute();
+
+ return false;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java b/src/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java
new file mode 100644
index 0000000..3aada4d
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/SendFileCommand.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antserver.commands;
+
+import java.io.*;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Util;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class SendFileCommand
+ extends AbstractCommand
+ implements Command
+{
+ private long contentLength;
+ private String todir;
+ private String tofile;
+ private String fileBaseName;
+ private transient File file;
+
+ public File getFile()
+ {
+ return file;
+ }
+
+ public long getContentLength()
+ {
+ return contentLength;
+ }
+
+ public InputStream getContentStream()
+ throws IOException
+ {
+ return new FileInputStream(file);
+ }
+
+ public void setFile(File file)
+ {
+ this.file = file;
+ this.fileBaseName = file.getName();
+ this.contentLength = file.length();
+ }
+
+
+ public String getTofile()
+ {
+ return tofile;
+ }
+
+
+ public void setTofile(String tofile)
+ {
+ this.tofile = tofile;
+ }
+
+
+ public String getTodir()
+ {
+ return todir;
+ }
+
+
+ public void setTodir(String todir)
+ {
+ this.todir = todir;
+ }
+
+ public void validate(Project project)
+ {
+ if (file == null)
+ throw new BuildException("Missing required attribute 'file'");
+
+ if (tofile == null && todir == null)
+ throw new BuildException("Missing both attributes 'tofile' and 'todir'"
+ + " at least one must be supplied");
+
+ /*
+ try
+ {
+ String realBasePath = project.getBaseDir().getCanonicalPath();
+ String realGetBasePath = file.getCanonicalPath();
+ if (! realGetBasePath.startsWith(realBasePath))
+ throw new SecurityException("Cannot access a file that is not rooted in the project execution directory");
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+ */
+
+
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ File dest = null;
+
+ if (tofile != null)
+ {
+ dest = new File(project.getBaseDir(), tofile);
+ if (! new File(tofile).getCanonicalPath().startsWith(project.getBaseDir().getCanonicalPath())) {
+ System.out.println("throwing an exception");
+ throw new SecurityException("The requested filename must be a relative path.");
+ }
+ }
+ else
+ {
+ dest = new File(project.getBaseDir(), todir);
+ dest = new File(dest, fileBaseName);
+
+ if (! new File(todir, tofile).getCanonicalPath().startsWith(project.getBaseDir().getCanonicalPath())) {
+ throw new SecurityException("The requested filename must be a relative path.");
+ }
+
+ }
+
+ FileOutputStream fos = null;
+
+ try
+ {
+ fos = new FileOutputStream(dest);
+
+ Util.transferBytes(content,
+ contentLength,
+ fos,
+ false);
+ }
+ finally
+ {
+ try
+ {
+ if (fos != null)
+ fos.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp;
+ }
+ }
+ return false;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java b/src/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java
new file mode 100644
index 0000000..6dcf226
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/commands/ShutdownCommand.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.commands;
+
+import java.io.InputStream;
+
+import org.apache.tools.ant.Project;
+
+import net.sf.antcontrib.antserver.Command;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ShutdownCommand
+ extends AbstractCommand
+ implements Command
+{
+ public void validate(Project project)
+ {
+ }
+
+ public boolean execute(Project project,
+ long contentLength,
+ InputStream content)
+ throws Throwable
+ {
+ return false;
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java b/src/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java
new file mode 100644
index 0000000..39cf1e5
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/server/ConnectionBuildListener.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.server;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.Stack;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.tools.ant.BuildEvent;
+import org.apache.tools.ant.BuildListener;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ConnectionBuildListener
+ implements BuildListener
+{
+ private Document results;
+ private Stack elementStack;
+ private ThreadGroup group;
+
+ public ConnectionBuildListener()
+ throws ParserConfigurationException
+ {
+ group = Thread.currentThread().getThreadGroup();
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ results = builder.newDocument();
+ elementStack = new Stack();
+
+ Element rootElement = results.createElement("results");
+ elementStack.push(rootElement);
+ results.appendChild(rootElement);
+ }
+
+ public Document getDocument()
+ {
+ return results;
+ }
+
+ public void buildStarted(BuildEvent event)
+ {
+ }
+
+
+ public void buildFinished(BuildEvent event)
+ {
+ }
+
+
+ public void targetStarted(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parent = (Element)elementStack.peek();
+
+ Element myElement = results.createElement("target");
+ myElement.setAttribute("name", event.getTarget().getName());
+ parent.appendChild(myElement);
+
+ elementStack.push(myElement);
+ }
+
+
+ public void targetFinished(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element myElement = (Element)elementStack.peek();
+
+ String message = event.getMessage();
+ if (message != null)
+ myElement.setAttribute("message", message);
+
+ Throwable t = event.getException();
+ if (t != null)
+ {
+ myElement.setAttribute("status", "failure");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ String errorMessage = t.getMessage();
+ String stackTrace = baos.toString();
+
+ Element error = results.createElement("error");
+ Element errorMsgElement = results.createElement("message");
+ errorMsgElement.appendChild(results.createTextNode(errorMessage));
+ Element stackElement = results.createElement("stack");
+ stackElement.appendChild(results.createCDATASection(stackTrace));
+ error.appendChild(errorMsgElement);
+ error.appendChild(stackElement);
+ myElement.appendChild(error);
+ }
+ else
+ {
+ myElement.setAttribute("status", "success");
+ }
+
+ elementStack.pop();
+ }
+
+
+ public void taskStarted(BuildEvent event)
+ {
+
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parent = (Element)elementStack.peek();
+
+ Element myElement = results.createElement("task");
+ myElement.setAttribute("name", event.getTask().getTaskName());
+ parent.appendChild(myElement);
+
+ elementStack.push(myElement);
+ }
+
+
+ public void taskFinished(BuildEvent event)
+ {
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element myElement = (Element)elementStack.peek();
+
+ Throwable t = event.getException();
+ if (t != null)
+ {
+ myElement.setAttribute("status", "failure");
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ PrintStream ps = new PrintStream(baos);
+ t.printStackTrace(ps);
+ ps.flush();
+ String errorMessage = t.getMessage();
+ String stackTrace = baos.toString();
+
+ Element error = results.createElement("error");
+ Element errorMsgElement = results.createElement("message");
+ errorMsgElement.appendChild(results.createTextNode(errorMessage));
+ Element stackElement = results.createElement("stack");
+ stackElement.appendChild(results.createCDATASection(stackTrace));
+ error.appendChild(errorMsgElement);
+ error.appendChild(stackElement);
+ myElement.appendChild(error);
+ }
+ else
+ {
+ myElement.setAttribute("status", "success");
+ }
+
+ elementStack.pop();
+ }
+
+
+ public void messageLogged(BuildEvent event)
+ {
+ /*
+ if (Thread.currentThread().getThreadGroup() != group)
+ return;
+
+ Element parentElement = (Element)elementStack.peek();
+
+ Element messageElement = results.createElement("message");
+ messageElement.setAttribute("level", String.valueOf(event.getPriority()));
+ messageElement.appendChild(results.createCDATASection(event.getMessage()));
+ parentElement.appendChild(messageElement);
+ */
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java b/src/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java
new file mode 100644
index 0000000..23169e0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/server/ConnectionHandler.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.server;
+
+import java.io.*;
+import java.net.Socket;
+
+import org.apache.tools.ant.Project;
+import org.apache.xml.serialize.OutputFormat;
+import org.apache.xml.serialize.XMLSerializer;
+
+import net.sf.antcontrib.antserver.Command;
+import net.sf.antcontrib.antserver.Response;
+import net.sf.antcontrib.antserver.Util;
+import net.sf.antcontrib.antserver.commands.DisconnectCommand;
+import net.sf.antcontrib.antserver.commands.ShutdownCommand;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ConnectionHandler
+ implements Runnable
+{
+ private static long nextGroupId = 0;
+ private ServerTask task;
+ private Socket socket;
+ private Thread thread;
+ private Throwable thrown;
+
+ public ConnectionHandler(ServerTask task, Socket socket)
+ {
+ super();
+ this.socket = socket;
+ this.task = task;
+ }
+
+ public void start()
+ {
+ long gid = nextGroupId;
+ if (nextGroupId == Long.MAX_VALUE)
+ nextGroupId = 0;
+ else
+ nextGroupId++;
+
+ ThreadGroup group = new ThreadGroup("server-tg-" + gid);
+ thread = new Thread(group, this);
+ thread.start();
+ }
+
+ public Throwable getThrown()
+ {
+ return thrown;
+ }
+
+ public void run()
+ {
+ InputStream is = null;
+ OutputStream os = null;
+
+
+ try
+ {
+ ConnectionBuildListener cbl = null;
+
+ is = socket.getInputStream();
+ os = socket.getOutputStream();
+
+ ObjectInputStream ois = new ObjectInputStream(is);
+ ObjectOutputStream oos = new ObjectOutputStream(os);
+
+ // Write the initial response object so that the
+ // object stream is initialized
+ oos.writeObject(new Response());
+
+ boolean disconnect = false;
+ Command inputCommand = null;
+ Response response = null;
+
+ while (! disconnect)
+ {
+ task.getProject().log("Reading command object.",
+ Project.MSG_DEBUG);
+
+ inputCommand = (Command) ois.readObject();
+
+ task.getProject().log("Executing command object: " + inputCommand,
+ Project.MSG_DEBUG);
+
+ response = new Response();
+
+ try
+ {
+ cbl = new ConnectionBuildListener();
+ task.getProject().addBuildListener(cbl);
+
+ inputCommand.execute(task.getProject(),
+ inputCommand.getContentLength(),
+ is);
+
+ response.setSucceeded(true);
+ }
+ catch (Throwable t)
+ {
+ response.setSucceeded(false);
+ response.setThrowable(t);
+ }
+ finally
+ {
+ if (cbl != null)
+ task.getProject().removeBuildListener(cbl);
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLSerializer serial = new XMLSerializer();
+ OutputFormat fmt = new OutputFormat();
+ fmt.setOmitDocumentType(true);
+ fmt.setOmitXMLDeclaration(false);
+ serial.setOutputFormat(fmt);
+ serial.setOutputByteStream(baos);
+ serial.serialize(cbl.getDocument());
+ response.setResultsXml(baos.toString());
+
+ task.getProject().log("Executed command object: " + inputCommand,
+ Project.MSG_DEBUG);
+
+ task.getProject().log("Sending response: " + response,
+ Project.MSG_DEBUG);
+
+ response.setContentLength(inputCommand.getContentLength());
+
+ oos.writeObject(response);
+
+ if (inputCommand.getResponseContentLength() != 0)
+ {
+ Util.transferBytes(inputCommand.getReponseContentStream(),
+ inputCommand.getResponseContentLength(),
+ os,
+ true);
+ }
+
+ if (inputCommand instanceof DisconnectCommand)
+ {
+ disconnect = true;
+ task.getProject().log("Got disconnect command",
+ Project.MSG_DEBUG);
+ }
+ else if (inputCommand instanceof ShutdownCommand)
+ {
+ disconnect = true;
+ task.getProject().log("Got shutdown command",
+ Project.MSG_DEBUG);
+ task.shutdown();
+ }
+
+ }
+
+ }
+ catch (ClassNotFoundException e)
+ {
+ thrown = e;
+ }
+ catch (IOException e)
+ {
+ thrown = e;
+ }
+ catch (Throwable t)
+ {
+ thrown = t;
+ }
+ finally
+ {
+ if (is != null)
+ {
+ try
+ {
+ is.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ if (os != null)
+ {
+ try
+ {
+ os.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ if (socket != null)
+ {
+ try
+ {
+ socket.close();
+ }
+ catch (IOException e)
+ {
+
+ }
+ }
+
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/antserver/server/Server.java b/src/java/net/sf/antcontrib/antserver/server/Server.java
new file mode 100644
index 0000000..b0e8c56
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/server/Server.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.server;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class Server
+ implements Runnable
+{
+ private ServerTask task;
+ private int port = 17000;
+ private boolean running = false;
+ private Thread thread = null;
+
+ public Server(ServerTask task, int port)
+ {
+ super();
+ this.task = task;
+ this.port = port;
+ }
+
+ public void start()
+ throws InterruptedException
+ {
+ thread = new Thread(this);
+ thread.start();
+ thread.join();
+ }
+
+ public void stop()
+ {
+ running = false;
+ }
+
+ public void run()
+ {
+ ServerSocket server = null;
+ running = true;
+ try
+ {
+ task.getProject().log("Starting server on port: " + port,
+ Project.MSG_DEBUG);
+ try
+ {
+ server = new ServerSocket(port);
+ server.setSoTimeout(500);
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+
+
+ while (running)
+ {
+ try
+ {
+ Socket clientSocket = server.accept();
+ task.getProject().log("Got a client connection. Starting Handler.",
+ Project.MSG_DEBUG);
+ ConnectionHandler handler = new ConnectionHandler(task,
+ clientSocket);
+ handler.start();
+ }
+ catch (InterruptedIOException e)
+ {
+ ; // gulp, no socket connection
+ }
+ catch (IOException e)
+ {
+ task.getProject().log(e.getMessage(),
+ Project.MSG_ERR);
+ }
+ }
+ }
+ finally
+ {
+ if (server != null)
+ {
+ try
+ {
+ server.close();
+ server = null;
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ }
+ }
+ running = false;
+
+
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/antserver/server/ServerTask.java b/src/java/net/sf/antcontrib/antserver/server/ServerTask.java
new file mode 100644
index 0000000..74006af
--- /dev/null
+++ b/src/java/net/sf/antcontrib/antserver/server/ServerTask.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.antserver.server;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ServerTask
+ extends Task
+{
+ private Server server;
+ private int port = 17000;
+
+ public ServerTask()
+ {
+ super();
+ }
+
+
+ public void setPort(int port)
+ {
+ this.port = port;
+ }
+
+
+ public void shutdown()
+ {
+ server.stop();
+ }
+
+ public void execute()
+ {
+ try
+ {
+ server = new Server(this, port);
+ server.start();
+ }
+ catch (InterruptedException e)
+ {
+ throw new BuildException(e);
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/design/Depends.java b/src/java/net/sf/antcontrib/design/Depends.java
new file mode 100644
index 0000000..570efc0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/Depends.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 24, 2004
+ */
+package net.sf.antcontrib.design;
+
+/**
+ *
+ * @author dhiller
+ */
+public class Depends {
+
+ private String name;
+
+ public Depends() {}
+ /**
+ * @param name
+ */
+ public Depends(String name) {
+ super();
+ this.name = name;
+ }
+ /**
+ * @param string
+ */
+ public void setName(String s) {
+ this.name = s;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toString() {
+ return name;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/design/Design.java b/src/java/net/sf/antcontrib/design/Design.java
new file mode 100644
index 0000000..6da018d
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/Design.java
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2001-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+
+
+/*
+ * Created on Aug 24, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class Design {
+
+ private Map nameToPackage = new HashMap();
+ private Map packageNameToPackage = new HashMap();
+ private boolean isCircularDesign;
+ private Log log;
+ private Location location;
+
+ private String currentClass = null;
+ private String currentPackageName = null;
+ private Package currentAliasPackage = null;
+
+ private HashSet primitives = new HashSet();
+
+ public Design(boolean isCircularDesign, Log log, Location loc) {
+ //by default, add java as a configured package with the name java
+ Package p = new Package();
+ p.setIncludeSubpackages(true);
+ p.setName("java");
+ p.setNeedDeclarations(false);
+ p.setPackage("java");
+ addConfiguredPackage(p);
+
+ this.isCircularDesign = isCircularDesign;
+ this.log = log;
+ this.location = loc;
+
+ primitives.add("boolean");
+
+ //integral types
+ primitives.add("byte");
+ primitives.add("short");
+ primitives.add("int");
+ primitives.add("long");
+ primitives.add("char");
+
+ //floating point types
+ primitives.add("double");
+ primitives.add("float");
+ }
+
+ public Package getPackage(String nameAttribute) {
+ return (Package)nameToPackage.get(nameAttribute);
+ }
+
+ private Package retreivePack(String thePackage) {
+ if(thePackage == null)
+ throw new IllegalArgumentException("Cannot retrieve null packages");
+
+ Package result = null;
+ String currentPackage = thePackage;
+ while(!Package.DEFAULT.equals(currentPackage)) {
+ result = (Package)packageNameToPackage.get(currentPackage);
+ if(result != null) {
+ if(currentPackage.equals(thePackage))
+ return result;
+ else if(result.isIncludeSubpackages())
+ return result;
+ return null;
+ }
+ currentPackage = VerifyDesignDelegate.getPackageName(currentPackage);
+ }
+
+ //result must now be default package
+ if(result != null && result.isIncludeSubpackages())
+ return result;
+
+ return null;
+ }
+
+ public void addConfiguredPackage(Package p) {
+
+ String pack = p.getPackage();
+
+ Depends[] depends = p.getDepends();
+
+ if(depends != null && !isCircularDesign) {
+ //make sure all depends are in Map first
+ //circular references then are not a problem because they must
+ //put the stuff in order
+ for(int i = 0; i < depends.length; i++) {
+ Package dependsPackage = (Package)nameToPackage.get(depends[i].getName());
+
+ if(dependsPackage == null) {
+ throw new RuntimeException("package name="+p.getName()+" did not\n" +
+ "have "+depends[i]+" listed before it. circularDesign is off\n"+
+ "so package="+p.getName()+" must be moved up in the xml file");
+ }
+ }
+ }
+
+ nameToPackage.put(p.getName(), p);
+ packageNameToPackage.put(p.getPackage(), p);
+ }
+
+ public void verifyDependencyOk(String className) {
+ log.log(" className="+className, Project.MSG_DEBUG);
+ if(className.startsWith("L"))
+ className = className.substring(1, className.length());
+
+ String classPackage = VerifyDesignDelegate.getPackageName(className);
+
+ //check if this is an needdeclarations="false" package, if so, the dependency is ok if it
+ //is not declared
+ log.log(" classPackage="+classPackage, Project.MSG_DEBUG);
+ Package p = retreivePack(classPackage);
+ if(p != null && !p.isNeedDeclarations())
+ return;
+
+ String pack = currentAliasPackage.getPackage();
+
+ log.log(" AllowedDepends="+pack, Project.MSG_DEBUG);
+ log.log(" CurrentDepends="+className, Project.MSG_DEBUG);
+ if(isClassInPackage(className, currentAliasPackage))
+ return;
+
+ Depends[] depends = currentAliasPackage.getDepends();
+
+ //probably want to create a regular expression out of all the depends and just match on that
+ //each time. for now though, just get it working and do the basic(optimize later if needed)
+ for(int i = 0; i < depends.length; i++) {
+ Depends d = depends[i];
+ String name = d.getName();
+
+ Package temp = getPackage(name);
+ log.log(" AllowedDepends="+temp.getPackage(), Project.MSG_DEBUG);
+ log.log(" CurrentDepends="+className, Project.MSG_DEBUG);
+ if(isClassInPackage(className, temp))
+ return;
+ }
+
+ log.log("***************************************", Project.MSG_DEBUG);
+ log.log("***************************************", Project.MSG_DEBUG);
+
+ throw new BuildException(Design.getErrorMessage(currentClass, className), location);
+ }
+
+ public boolean isClassInPackage(String className, Package p) {
+ String classPackage = VerifyDesignDelegate.getPackageName(className);
+ if(p.isIncludeSubpackages()) {
+ if(className.startsWith(p.getPackage()))
+ return true;
+ } else { //if not including subpackages, the it must be the exact package.
+ if(classPackage.equals(p.getPackage()))
+ return true;
+ }
+ return false;
+ }
+ /**
+ * @param className
+ * @return whether or not this class needs to be checked. (ie. if the
+ * attribute needdepends=false, we don't care about this package.
+ */
+ public boolean needEvalCurrentClass(String className) {
+ currentClass = className;
+ String packageName = VerifyDesignDelegate.getPackageName(className);
+// log("class="+className, Project.MSG_DEBUG);
+ if(!packageName.equals(currentPackageName) || currentAliasPackage == null) {
+ currentPackageName = packageName;
+ log.log("\nEvaluating package="+currentPackageName, Project.MSG_INFO);
+ currentAliasPackage = retreivePack(packageName);
+ //DEANDO: test this scenario
+ if(currentAliasPackage == null) {
+ log.log(" class="+className, Project.MSG_VERBOSE);
+ throw new BuildException(getNoDefinitionError(className), location);
+ }
+ }
+ log.log(" class="+className, Project.MSG_VERBOSE);
+
+ if(!className.startsWith(currentPackageName))
+ throw new RuntimeException("Internal Error");
+
+ if(!currentAliasPackage.getNeedDepends())
+ return false;
+ return true;
+ }
+
+ public String getCurrentClass() {
+ return currentClass;
+ }
+
+ void checkClass(String dependsOn) {
+ log.log(" dependsOn1="+dependsOn, Project.MSG_DEBUG);
+ if(dependsOn.endsWith("[]")) {
+ int index = dependsOn.indexOf("[");
+ dependsOn = dependsOn.substring(0, index);
+ log.log(" dependsOn2="+dependsOn, Project.MSG_DEBUG);
+ }
+
+ if(primitives.contains(dependsOn))
+ return;
+
+ //Anything in java.lang package seems to be passed in as just the
+ //className with no package like Object, String or Class, so here we try to
+ //see if the name is a java.lang class....
+ String tempTry = "java.lang."+dependsOn;
+ try {
+ Class c = VerifyDesign.class.getClassLoader().loadClass(tempTry);
+ return;
+ } catch(ClassNotFoundException e) {
+ //not found, continue on...
+ }
+ //sometimes instead of passing java.lang.String or java.lang.Object, the bcel
+ //passes just String or Object
+// if("String".equals(dependsOn) || "Object".equals(dependsOn))
+// return;
+
+ verifyDependencyOk(dependsOn);
+
+ }
+
+ public static String getErrorMessage(String className, String dependsOnClass) {
+ String s = "\nYou are violating your own design...." +
+ "\nClass = "+className+" depends on\nClass = "+dependsOnClass+
+ "\nThe dependency to allow this is not defined in your design" +
+ "\nPackage="+VerifyDesignDelegate.getPackageName(className)+" is not defined to depend on"+
+ "\nPackage="+VerifyDesignDelegate.getPackageName(dependsOnClass)+
+ "\nChange the code or the design";
+ return s;
+ }
+
+ public static String getNoDefinitionError(String className) {
+ String s = "\nPackage="+VerifyDesignDelegate.getPackageName(className)+" is not defined in the design.\n"+
+ "All packages with classes must be declared in the design file\n"+
+ "Class found in the offending package="+className;
+ return s;
+ }
+
+ public static String getWrapperMsg(File originalFile, String message) {
+ String s = "\nThe file '" + originalFile.getAbsolutePath() + "' failed due to: " + message;
+ return s;
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/design/DesignFileHandler.java b/src/java/net/sf/antcontrib/design/DesignFileHandler.java
new file mode 100644
index 0000000..52e1bf2
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/DesignFileHandler.java
@@ -0,0 +1,336 @@
+/*
+ * Copyright (c) 2004-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import java.io.File;
+import java.util.Stack;
+
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**
+ * Handler for the root element. Its only child must be the "project" element.
+ */
+class DesignFileHandler implements ContentHandler {
+
+ private final static String DESIGN = "design";
+ private final static String PACKAGE = "package";
+ private final static String DEPENDS = "depends";
+
+ private Log log = null;
+ private File file = null;
+ private boolean isCircularDesign;
+ private boolean needDeclarationsDefault = true;
+ private boolean needDependsDefault = true;
+
+ private Design design = null;
+ private Package currentPackage = null;
+ private Stack stack = new Stack();
+ private Locator locator = null;
+ private Location loc;
+
+ /**
+ * @param CompileWithWalls
+ */
+ DesignFileHandler(Log log, File file, boolean isCircularDesign, Location loc) {
+ this.log = log;
+ this.file = file;
+ this.isCircularDesign = isCircularDesign;
+ this.loc = loc;
+ }
+
+ /**
+ * @param needDeclarationsDefault
+ */
+ public void setNeedDeclarationsDefault(boolean b) {
+ needDeclarationsDefault = b;
+ }
+
+ /**
+ * @param needDependsDefault
+ */
+ public void setNeedDependsDefault(boolean b) {
+ needDependsDefault = b;
+ }
+
+ public Design getDesign() {
+ return design;
+ }
+
+ /**
+ * Resolves file: URIs relative to the build file.
+ *
+ * @param publicId The public identifer, or <code>null</code>
+ * if none is available. Ignored in this
+ * implementation.
+ * @param systemId The system identifier provided in the XML
+ * document. Will not be <code>null</code>.
+ */
+ public InputSource resolveEntity(String publicId,
+ String systemId) {
+ log.log("publicId="+publicId+" systemId="+systemId,
+ Project.MSG_VERBOSE);
+ return null;
+ }
+
+ /**
+ * Sets the locator in the project helper for future reference.
+ *
+ * @param locator The locator used by the parser.
+ * Will not be <code>null</code>.
+ */
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)
+ */
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)
+ */
+ public void endPrefixMapping(String prefix) throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
+ */
+ public void startElement(String uri, String name, String qName, Attributes attrs) throws SAXException {
+ log.log("Parsing startElement="+name, Project.MSG_DEBUG);
+ if (name == null || "".equals(name)) {
+ // XMLReader is not-namespace aware
+ name = qName;
+ }
+
+ try {
+ Object o = null;
+ if(name.equals(DESIGN)) {
+ o = handleDesign(attrs);
+ } else if(name.equals(PACKAGE)) {
+ currentPackage = handlePackage(attrs);
+ o = currentPackage;
+ } else if(name.equals(DEPENDS)) {
+ o = handleDepends(attrs);
+ } else {
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", Unexpected element \"" + name + "\"", locator);
+ }
+ stack.push(o);
+ } catch(RuntimeException e) {
+ log.log("exception111111111111111111", Project.MSG_INFO);
+ throw new SAXParseException("PRoblem parsing", locator, e);
+ }
+ }
+
+ private Design handleDesign(Attributes attrs) throws SAXParseException {
+ if(attrs.getLength() > 0)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", no attributes allowed for "+DESIGN+" element", locator);
+ else if(stack.size() > 0)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", "+DESIGN+" cannot be a subelement of "+stack.pop(), locator);
+ else if(attrs.getLength() > 0)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", "+DESIGN+" element can't have any attributes", locator);
+ design = new Design(isCircularDesign, log, loc);
+ return design;
+ }
+
+ private Package handlePackage(Attributes attrs) throws SAXParseException {
+ if(stack.size() <= 0 || !(stack.peek() instanceof Design))
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", "+PACKAGE+" element must be nested in a "+DESIGN+" element", locator);
+
+ int len = attrs.getLength();
+ String name = null;
+ String thePackage = null;
+ String depends = null;
+ String subpackages = null;
+ String needDeclarations = null;
+ String needDepends = null;
+ for(int i = 0; i < len; i++) {
+ String attrName = attrs.getLocalName(i);
+
+ if ("".equals(attrName)) {
+ // XMLReader is not-namespace aware
+ attrName = attrs.getQName(i);
+ }
+ String value = attrs.getValue(i);
+ log.log("attr="+attrName+" value="+value, Project.MSG_DEBUG);
+ if("name".equals(attrName))
+ name = value;
+ else if("package".equals(attrName))
+ thePackage = value;
+ else if("depends".equals(attrName))
+ depends = value;
+ else if("subpackages".equals(attrName))
+ subpackages = value;
+ else if("needdeclarations".equals(attrName))
+ needDeclarations = value;
+ else if("needdepends".equals(attrName))
+ needDepends = value;
+ else
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +"\n'"+attrName+"' attribute is an invalid attribute for the package element", locator);
+ }
+
+ //set the defaults
+ if(subpackages == null)
+ subpackages = "exclude";
+ if(needDeclarations == null)
+ needDeclarations = Boolean.toString(needDeclarationsDefault);
+ if(needDepends == null)
+ needDepends = Boolean.toString(needDependsDefault);
+
+ //make sure every attribute had a valid value...
+ if(name == null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", package element must contain the 'name' attribute", locator);
+ else if(thePackage == null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", package element must contain the 'package' attribute", locator);
+ else if(!("include".equals(subpackages) || "exclude".equals(subpackages)))
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +"\nThe subpackages attribute in the package element can only have a"
+ +"\nvalue of \"include\" or \"exclude\". value='"+subpackages+"'", locator);
+ else if(!("true".equals(needDeclarations) || "false".equals(needDeclarations)))
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +"\nThe needdeclarations attribute in the package element can only have a"
+ +"\nvalue of \"true\" or \"false\". value='"+needDeclarations+"'", locator);
+ else if(!("true".equals(needDepends) || "false".equals(needDepends)))
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +"\nThe needdepends attribute in the package element can only have a"
+ +"\nvalue of \"true\" or \"false\". value='"+needDepends+"'", locator);
+
+ Package p = new Package();
+ p.setName(name);
+ p.setPackage(thePackage);
+ if("exclude".equals(subpackages))
+ p.setIncludeSubpackages(false);
+ else
+ p.setIncludeSubpackages(true);
+ if("true".equals(needDeclarations))
+ p.setNeedDeclarations(true);
+ else
+ p.setNeedDeclarations(false);
+ if("true".equals(needDepends))
+ p.setNeedDepends(true);
+ else
+ p.setNeedDepends(false);
+
+ if(depends != null)
+ p.addDepends(new Depends(depends));
+ return p;
+ }
+
+ private Depends handleDepends(Attributes attrs) throws SAXParseException {
+ if(stack.size() <= 0 || !(stack.peek() instanceof Package))
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", "+DEPENDS+" element must be nested in a "+PACKAGE+" element", locator);
+ else if(attrs.getLength() > 0)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", "+DEPENDS+" element can't have any attributes", locator);
+
+ return new Depends();
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ try {
+ Object o = stack.pop();
+ if(o instanceof Package) {
+ Package p = (Package)o;
+
+ Package tmp = design.getPackage(p.getName());
+ if(tmp != null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +"\nname attribute on "+PACKAGE+" element has the same\n"
+ +"name as another package. name=\""+p.getName()+"\" is used twice or more", locator);
+
+
+ design.addConfiguredPackage(p);
+ currentPackage = null;
+ } else if(o instanceof Depends) {
+ Depends d = (Depends)o;
+ currentPackage.addDepends(d);
+ }
+ } catch(RuntimeException e) {
+ throw new SAXParseException("exception", locator, e);
+ }
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)
+ */
+ public void skippedEntity(String name) throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#startDocument()
+ */
+ public void startDocument() throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#endDocument()
+ */
+ public void endDocument() throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#characters(char[], int, int)
+ */
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ try {
+ Object o = stack.peek();
+ if(o instanceof Depends) {
+ String s = new String(ch, start, length);
+ Depends d = (Depends)o;
+ if (d.getName() != null)
+ d.setName(d.getName() + s.trim());
+ else
+ d.setName(s.trim());
+ }
+ } catch(RuntimeException e) {
+ log.log("exception3333333333333333333", Project.MSG_INFO);
+ throw new SAXParseException("exception", locator, e);
+ }
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)
+ */
+ public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {
+ }
+
+ /**
+ * @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)
+ */
+ public void processingInstruction(String target, String data) throws SAXException {
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/design/InstructionVisitor.java b/src/java/net/sf/antcontrib/design/InstructionVisitor.java
new file mode 100644
index 0000000..eb4c920
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/InstructionVisitor.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import org.apache.bcel.generic.ANEWARRAY;
+import org.apache.bcel.generic.CHECKCAST;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.EmptyVisitor;
+import org.apache.bcel.generic.INSTANCEOF;
+import org.apache.bcel.generic.INVOKESTATIC;
+import org.apache.bcel.generic.LoadInstruction;
+import org.apache.bcel.generic.NEW;
+import org.apache.bcel.generic.PUTSTATIC;
+import org.apache.bcel.generic.Type;
+import org.apache.tools.ant.Project;
+
+
+
+public class InstructionVisitor extends EmptyVisitor {
+
+
+ private ConstantPoolGen poolGen;
+ private Log log;
+ private Design design;
+
+ /**
+ * @param poolGen
+ * @param v
+ */
+ public InstructionVisitor(ConstantPoolGen poolGen, Log log, Design d) {
+ this.poolGen = poolGen;
+ this.log = log;
+ this.design = d;
+ }
+
+ public void visitCHECKCAST(CHECKCAST c) {
+ Type t = c.getType(poolGen);
+ log.log(" instr(checkcast)="+t, Project.MSG_DEBUG);
+ String type = t.toString();
+
+ design.checkClass(type);
+ }
+
+ public void visitLoadInstruction(LoadInstruction l) {
+ //log.log(" visit load", Project.MSG_DEBUG);
+ Type t = l.getType(poolGen);
+ log.log(" instr(loadinstr)="+t, Project.MSG_DEBUG);
+ String type = t.toString();
+
+ design.checkClass(type);
+ }
+
+ public void visitNEW(NEW n) {
+ Type t= n.getType(poolGen);
+ log.log(" instr(new)="+t, Project.MSG_DEBUG);
+ String type = t.toString();
+
+ design.checkClass(type);
+ }
+
+ public void visitANEWARRAY(ANEWARRAY n) {
+ Type t = n.getType(poolGen);
+ log.log(" instr(anewarray)="+t, Project.MSG_DEBUG);
+ String type = t.toString();
+
+ design.checkClass(type);
+ }
+
+ public void visitINSTANCEOF(INSTANCEOF i) {
+ Type t = i.getType(poolGen);
+ log.log(" instr(instanceof)="+t, Project.MSG_DEBUG);
+ String type = t.toString();
+
+ design.checkClass(type);
+ }
+ public void visitINVOKESTATIC(INVOKESTATIC s) {
+ String t = s.getClassName(poolGen);
+ log.log(" instr(invokestatic)="+t, Project.MSG_DEBUG);
+
+ design.checkClass(t);
+ }
+
+ public void visitPUTSTATIC(PUTSTATIC s) {
+ String one = s.getClassName(poolGen);
+ String two = s.getFieldName(poolGen);
+ String three = s.getName(poolGen);
+ String four = s.getSignature(poolGen);
+ String five = s.getClassType(poolGen)+"";
+ String six = s.getFieldType(poolGen)+"";
+ log.log(" instr(putstatic)a="+one, Project.MSG_DEBUG);
+ log.log(" instr(putstatic)b="+two, Project.MSG_DEBUG);
+ log.log(" instr(putstatic)c="+three, Project.MSG_DEBUG);
+ log.log(" instr(putstatic)d="+four, Project.MSG_DEBUG);
+ log.log(" instr(putstatic)e="+five, Project.MSG_DEBUG);
+ log.log(" instr(putstatic)f="+six, Project.MSG_DEBUG);
+
+ String className = s.getFieldName(poolGen);
+ if("staticField".equals(className))
+ return;
+
+ if(className.startsWith("class$") || className.startsWith("array$"))
+ ;
+ else return;
+
+ log.log(" instr(putstatic)1="+className, Project.MSG_DEBUG);
+ className = className.substring(6, className.length());
+ log.log(" instr(putstatic)2="+className, Project.MSG_DEBUG);
+ className = className.replace('$', '.');
+ log.log(" instr(putstatic)3="+className, Project.MSG_DEBUG);
+
+ design.checkClass(className);
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/design/Log.java b/src/java/net/sf/antcontrib/design/Log.java
new file mode 100644
index 0000000..466dcdc
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/Log.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 24, 2004
+ */
+package net.sf.antcontrib.design;
+
+/**
+ *
+ * @author dhiller
+ */
+public interface Log {
+
+ public void log(String s, int level);
+}
diff --git a/src/java/net/sf/antcontrib/design/Package.java b/src/java/net/sf/antcontrib/design/Package.java
new file mode 100644
index 0000000..a470f8c
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/Package.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+/*
+ * Created on Aug 24, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class Package {
+
+ public final static String DEFAULT = "<default package>";
+ private String name;
+ private String pack;
+
+ //holds the name attribute of the package element of each
+ //package this package depends on.
+ private List depends;
+ private boolean isIncludeSubpackages;
+ private boolean needDeclarations;
+ private boolean needDepends;
+
+ public void setName(String name) {
+ if("".equals(name))
+ name = DEFAULT;
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public void setPackage(String pack) {
+ this.pack = pack;
+ }
+
+ public String getPackage() {
+ return pack;
+ }
+
+ public void addDepends(Depends d) {
+ if(depends == null)
+ depends = new ArrayList();
+ depends.add(d);
+ }
+
+ public Depends[] getDepends() {
+ Depends[] d = new Depends[0];
+ if(depends == null)
+ return d;
+ return (Depends[])depends.toArray(d);
+ }
+
+ /**
+ * @param b
+ */
+ public void setIncludeSubpackages(boolean b) {
+ isIncludeSubpackages = b;
+ }
+ /**
+ * @return
+ */
+ public boolean isIncludeSubpackages() {
+ return isIncludeSubpackages;
+ }
+ /**
+ * @param b
+ */
+ public void setNeedDeclarations(boolean b) {
+ needDeclarations = b;
+ }
+ /**
+ * @return
+ */
+ public boolean isNeedDeclarations() {
+ return needDeclarations;
+ }
+ /**
+ * @param b
+ */
+ public void setNeedDepends(boolean b) {
+ needDepends = b;
+ }
+
+ public boolean getNeedDepends() {
+ return needDepends;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/design/VerifyDesign.java b/src/java/net/sf/antcontrib/design/VerifyDesign.java
new file mode 100644
index 0000000..dfffd47
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/VerifyDesign.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2004-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+
+/**
+ * @author dhiller
+ */
+public class VerifyDesign
+ extends Task
+ implements Log {
+
+ private VerifyDesignDelegate delegate;
+
+ public VerifyDesign() {
+ delegate = new VerifyDesignDelegate(this);
+ }
+
+ public void setJar(File f) {
+ delegate.setJar(f);
+ }
+
+ public void setDesign(File f) {
+ delegate.setDesign(f);
+ }
+
+ public void setCircularDesign(boolean isCircularDesign) {
+ delegate.setCircularDesign(isCircularDesign);
+ }
+
+ public void setDeleteFiles(boolean deleteFiles) {
+ delegate.setDeleteFiles(deleteFiles);
+ }
+
+ public void setFillInBuildException(boolean b) {
+ delegate.setFillInBuildException(b);
+ }
+
+ public void setNeedDeclarationsDefault(boolean b) {
+ delegate.setNeedDeclarationsDefault(b);
+ }
+
+ public void setNeedDependsDefault(boolean b) {
+ delegate.setNeedDependsDefault(b);
+ }
+
+ public void addConfiguredPath(Path path) {
+ delegate.addConfiguredPath(path);
+ }
+ public void execute()
+ throws BuildException {
+ delegate.execute();
+ }
+}
diff --git a/src/java/net/sf/antcontrib/design/VerifyDesignDelegate.java b/src/java/net/sf/antcontrib/design/VerifyDesignDelegate.java
new file mode 100644
index 0000000..1c2fb01
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/VerifyDesignDelegate.java
@@ -0,0 +1,424 @@
+/*
+ * Copyright (c) 2004-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.antcontrib.design;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Vector;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.ClassFormatException;
+import org.apache.bcel.classfile.ClassParser;
+import org.apache.bcel.classfile.Constant;
+import org.apache.bcel.classfile.ConstantClass;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.ConstantUtf8;
+import org.apache.bcel.classfile.DescendingVisitor;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.Utility;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.PatternSet;
+import org.apache.tools.ant.util.JAXPUtils;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/**
+ *
+ *
+ *
+ * @author dhiller
+ *
+ */
+
+public class VerifyDesignDelegate implements Log {
+
+ private File designFile;
+ private Vector paths = new Vector();
+ private boolean isCircularDesign = false;
+ private boolean deleteFiles = false;
+ private boolean fillInBuildException = false;
+ private boolean needDeclarationsDefault = true;
+ private boolean needDependsDefault = true;
+
+ private Task task;
+ private Design design;
+ private HashSet primitives = new HashSet();
+ private Vector designErrors = new Vector();
+ private boolean verifiedAtLeastOne = false;
+
+ public VerifyDesignDelegate(Task task) {
+ this.task = task;
+ primitives.add("B");
+ primitives.add("C");
+ primitives.add("D");
+ primitives.add("F");
+ primitives.add("I");
+ primitives.add("J");
+ primitives.add("S");
+ primitives.add("Z");
+ }
+
+ public void addConfiguredPath(Path path) {
+// Path newPath = new Path(task.getProject());
+// path.
+
+
+ paths.add(path);
+ }
+
+ public void setJar(File f) {
+ Path p = (Path)task.getProject().createDataType("path");
+ p.createPathElement().setLocation(f.getAbsoluteFile());
+ addConfiguredPath(p);
+ }
+
+ public void setDesign(File f) {
+ this.designFile = f;
+ }
+
+ public void setCircularDesign(boolean isCircularDesign) {
+ this.isCircularDesign = isCircularDesign;
+ }
+
+ public void setDeleteFiles(boolean deleteFiles) {
+ this.deleteFiles = deleteFiles;
+ }
+
+ public void setFillInBuildException(boolean b) {
+ fillInBuildException = b;
+ }
+
+ public void setNeedDeclarationsDefault(boolean b) {
+ needDeclarationsDefault = b;
+ }
+
+ public void setNeedDependsDefault(boolean b) {
+ needDependsDefault = b;
+ }
+
+ public void execute() {
+ if(!designFile.exists() || designFile.isDirectory())
+ throw new BuildException("design attribute in verifydesign element specified an invalid file="+designFile);
+
+ verifyJarFilesExist();
+
+ try {
+ XMLReader reader = JAXPUtils.getXMLReader();
+ DesignFileHandler ch = new DesignFileHandler(this, designFile, isCircularDesign, task.getLocation());
+ ch.setNeedDeclarationsDefault(needDeclarationsDefault);
+ ch.setNeedDependsDefault(needDependsDefault);
+ reader.setContentHandler(ch);
+ //reader.setEntityResolver(ch);
+ //reader.setErrorHandler(ch);
+ //reader.setDTDHandler(ch);
+
+ log("about to start parsing file='"+designFile+"'", Project.MSG_INFO);
+ FileInputStream fileInput = new FileInputStream(designFile);
+ InputSource src = new InputSource(fileInput);
+ reader.parse(src);
+ design = ch.getDesign();
+
+ Enumeration pathsEnum = paths.elements();
+ Path p = null;
+ while (pathsEnum.hasMoreElements()) {
+ p = (Path)pathsEnum.nextElement();
+ verifyPathAdheresToDesign(design, p);
+ }
+
+ if (! designErrors.isEmpty()) {
+ log(designErrors.size()+"Errors.", Project.MSG_WARN);
+ if(!fillInBuildException)
+ throw new BuildException("Design check failed due to previous errors");
+ throwAllErrors();
+ }
+
+ } catch (SAXException e) {
+ maybeDeleteFiles();
+ if (e.getException() != null
+ && e.getException() instanceof RuntimeException)
+ throw (RuntimeException) e.getException();
+ else if (e instanceof SAXParseException) {
+ SAXParseException pe = (SAXParseException) e;
+ throw new BuildException("\nProblem parsing design file='"
+ + designFile + "'. \nline=" + pe.getLineNumber()
+ + " column=" + pe.getColumnNumber() + " Reason:\n"
+ + e.getMessage() + "\n", e);
+ }
+ throw new BuildException("\nProblem parsing design file='"
+ + designFile + "'. Reason:\n" + e, e);
+ } catch (IOException e) {
+ maybeDeleteFiles();
+ throw new RuntimeException("See attached exception", e);
+ // throw new BuildException("IOException on design file='"
+ // + designFile + "'. attached:", e);
+ } catch(RuntimeException e) {
+ maybeDeleteFiles();
+ throw e;
+ } finally {
+
+ }
+
+ if(!verifiedAtLeastOne)
+ throw new BuildException("Did not find any class or jar files to verify");
+ }
+ //some auto builds like cruisecontrol can only report all the
+ //standard ant task errors and the build exceptions so here
+ //we need to fill in the buildexception so the errors are reported
+ //correctly through those tools....though, you think ant has a hook
+ //in that cruisecontrol is not using like LogListeners or something
+ private void throwAllErrors() {
+ String result = "Design check failed due to following errors";
+ Enumeration exceptions = designErrors.elements();
+ while(exceptions.hasMoreElements()) {
+ BuildException be = (BuildException)exceptions.nextElement();
+ String message = be.getMessage();
+ result += "\n" + message;
+ }
+ throw new BuildException(result);
+ }
+
+ private void verifyJarFilesExist() {
+ Enumeration pathsEnum = paths.elements();
+ Path p = null;
+ while (pathsEnum.hasMoreElements()) {
+ p = (Path)pathsEnum.nextElement();
+ String files[] = p.list();
+ for (int i=0;i<files.length;i++) {
+ File file = new File(files[i]);
+
+ if (!file.exists())
+ throw new BuildException(VisitorImpl.getNoFileMsg(file));
+ }
+ }
+ }
+
+ private void maybeDeleteFiles() {
+ if (deleteFiles) {
+ log("Deleting all class and jar files so you do not get tempted to\n" +
+ "use a jar that doesn't abide by the design(This option can\n" +
+ "be turned off if you really want)", Project.MSG_INFO);
+
+ Enumeration pathsEnum = paths.elements();
+ Path p = null;
+ while (pathsEnum.hasMoreElements()) {
+ p = (Path)pathsEnum.nextElement();
+ deleteFilesInPath(p);
+ }
+ }
+ }
+
+ private void deleteFilesInPath(Path p) {
+ String files[] = p.list();
+ for (int i=0;i<files.length;i++) {
+ File file = new File(files[i]);
+
+ boolean deleted = file.delete();
+ if (! deleted) {
+ file.deleteOnExit();
+ }
+ }
+ }
+
+ private void verifyPathAdheresToDesign(Design d, Path p) throws ClassFormatException, IOException {
+ String files[] = p.list();
+ for (int i=0;i<files.length;i++) {
+ File file = new File(files[i]);
+ if(file.isDirectory()) {
+ FileSet set = new FileSet();
+ set.setDir(file);
+ set.setProject(task.getProject());
+ PatternSet.NameEntry entry1 = set.createInclude();
+ PatternSet.NameEntry entry2 = set.createInclude();
+ PatternSet.NameEntry entry3 = set.createInclude();
+ entry1.setName("**/*.class");
+ entry2.setName("**/*.jar");
+ entry3.setName("**/*.war");
+ DirectoryScanner scanner = set.getDirectoryScanner(task.getProject());
+ scanner.setBasedir(file);
+ String[] scannerFiles = scanner.getIncludedFiles();
+ for(int j = 0; j < scannerFiles.length; j++) {
+ verifyPartOfPath(scannerFiles[j], new File(file, scannerFiles[j]), d);
+ }
+ } else
+ verifyPartOfPath(files[i], file, d);
+ }
+ }
+
+ private void verifyPartOfPath(String fileName, File file, Design d) throws IOException {
+ if (fileName.endsWith(".jar") || fileName.endsWith(".war")) {
+ JarFile jarFile = new JarFile(file);
+ verifyJarAdheresToDesign(d, jarFile, file);
+ } else if (fileName.endsWith(".class")) {
+ verifyClassAdheresToDesign(d, file);
+ } else
+ throw new BuildException("Only directories, jars, wars, and class files can be supplied to verify design, not file="+file.getAbsolutePath());
+ }
+
+ private void verifyClassAdheresToDesign(Design d, File classFile)
+ throws ClassFormatException, IOException {
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(classFile);
+ verifyClassAdheresToDesign(d, fis, classFile.getAbsolutePath(), classFile);
+ }
+ finally {
+ try {
+ if (fis != null) {
+ fis.close();
+ }
+ }
+ catch (IOException e) {
+ ; //doh!!
+ }
+ }
+
+ }
+
+ private void verifyJarAdheresToDesign(Design d, JarFile jarFile, File original)
+ throws ClassFormatException, IOException {
+
+ try {
+ Enumeration en = jarFile.entries();
+ while(en.hasMoreElements()) {
+ ZipEntry entry = (ZipEntry)en.nextElement();
+ InputStream in = null;
+ if(entry.getName().endsWith(".class")) {
+ in = jarFile.getInputStream(entry);
+ try {
+ in = jarFile.getInputStream(entry);
+ verifyClassAdheresToDesign(d, in, entry.getName(), original);
+ }
+ finally {
+ try {
+ if (in != null) {
+ in.close();
+ }
+ }
+ catch (IOException e) {
+ ; // doh!!!
+ }
+ }
+ }
+ }
+ }
+ finally {
+ try {
+ jarFile.close();
+ }
+ catch (IOException e) {
+ ; //doh!!!
+ }
+ }
+ }
+
+ private String className = "";
+
+ private void verifyClassAdheresToDesign(Design d, InputStream in, String name, File originalClassOrJarFile) throws ClassFormatException, IOException {
+ try {
+ verifiedAtLeastOne = true;
+ ClassParser parser = new ClassParser(in, name);
+ JavaClass javaClass = parser.parse();
+ className = javaClass.getClassName();
+
+ if(!d.needEvalCurrentClass(className))
+ return;
+
+ ConstantPool pool = javaClass.getConstantPool();
+ processConstantPool(pool);
+ VisitorImpl visitor = new VisitorImpl(pool, this, d, task.getLocation());
+ DescendingVisitor desc = new DescendingVisitor(javaClass, visitor);
+ desc.visit();
+ } catch(BuildException e) {
+ log(Design.getWrapperMsg(originalClassOrJarFile, e.getMessage()), Project.MSG_ERR);
+ designErrors.addElement(e);
+ }
+ }
+
+ private void processConstantPool(ConstantPool pool) {
+ Constant[] constants = pool.getConstantPool();
+ if(constants == null) {
+ log(" constants=null", Project.MSG_VERBOSE);
+ return;
+ }
+
+ log(" constants len="+constants.length, Project.MSG_VERBOSE);
+ for(int i = 0; i < constants.length; i++) {
+ processConstant(pool, constants[i], i);
+ }
+ }
+
+ private void processConstant(ConstantPool pool, Constant c, int i) {
+ if(c == null) //don't know why, but constant[0] seems to be always null.
+ return;
+
+ log(" const["+i+"]="+pool.constantToString(c)+" inst="+c.getClass().getName(), Project.MSG_DEBUG);
+ byte tag = c.getTag();
+ switch(tag) {
+ //reverse engineered from ConstantPool.constantToString..
+ case Constants.CONSTANT_Class:
+ int ind = ((ConstantClass)c).getNameIndex();
+ c = pool.getConstant(ind, Constants.CONSTANT_Utf8);
+ String className = Utility.compactClassName(((ConstantUtf8)c).getBytes(), false);
+ log(" classNamePre="+className, Project.MSG_DEBUG);
+ className = getRidOfArray(className);
+ String firstLetter = className.charAt(0)+"";
+ if(primitives.contains(firstLetter))
+ return;
+ log(" className="+className, Project.MSG_VERBOSE);
+ design.checkClass(className);
+ break;
+ default:
+
+ }
+ }
+
+ private static String getRidOfArray(String className) {
+ while(className.startsWith("["))
+ className = className.substring(1, className.length());
+ return className;
+ }
+
+ public static String getPackageName(String className) {
+ String packageName = Package.DEFAULT;
+ int index = className.lastIndexOf(".");
+ if(index > 0)
+ packageName = className.substring(0, index);
+ //DEANDO: test the else scenario here(it is a corner case)...
+
+ return packageName;
+ }
+
+ public void log(String msg, int level) {
+ //if(level == Project.MSG_WARN || level == Project.MSG_INFO
+ // || level == Project.MSG_ERR || level == Project.MSG_VERBOSE)
+ //VerifyDesignTest.log(msg);
+ task.log(msg, level);
+ }
+}
diff --git a/src/java/net/sf/antcontrib/design/VisitorImpl.java b/src/java/net/sf/antcontrib/design/VisitorImpl.java
new file mode 100644
index 0000000..84aefee
--- /dev/null
+++ b/src/java/net/sf/antcontrib/design/VisitorImpl.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package net.sf.antcontrib.design;
+
+import java.io.File;
+
+import org.apache.bcel.Constants;
+import org.apache.bcel.classfile.Code;
+import org.apache.bcel.classfile.CodeException;
+import org.apache.bcel.classfile.ConstantPool;
+import org.apache.bcel.classfile.EmptyVisitor;
+import org.apache.bcel.classfile.ExceptionTable;
+import org.apache.bcel.classfile.Field;
+import org.apache.bcel.classfile.JavaClass;
+import org.apache.bcel.classfile.LineNumberTable;
+import org.apache.bcel.classfile.LocalVariable;
+import org.apache.bcel.classfile.Method;
+import org.apache.bcel.classfile.Utility;
+import org.apache.bcel.generic.ConstantPoolGen;
+import org.apache.bcel.generic.Instruction;
+import org.apache.bcel.generic.InstructionHandle;
+import org.apache.bcel.generic.MethodGen;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+
+class VisitorImpl extends EmptyVisitor {
+
+ private ConstantPool pool;
+ private Log log;
+ private Design design;
+ private ConstantPoolGen poolGen;
+ private InstructionVisitor visitor;
+ private Location location;
+
+ public VisitorImpl(ConstantPool pool, Log log, Design d, Location loc) {
+ this.pool = pool;
+ this.log = log;
+ this.design = d;
+ this.location = loc;
+ this.poolGen = new ConstantPoolGen(pool);
+ visitor = new InstructionVisitor(poolGen, log, d);
+ }
+
+ private void log(String s, int level) {
+ log.log(s, level);
+ }
+
+ public void visitJavaClass(JavaClass c) {
+ log(" super=" + c.getSuperclassName(), Project.MSG_VERBOSE);
+ String[] names = c.getInterfaceNames();
+
+ String superClass = c.getSuperclassName();
+
+ design.checkClass(superClass);
+
+ for (int i = 0; i < names.length; i++) {
+ log(" interfaces=" + names[i], Project.MSG_VERBOSE);
+ design.checkClass(names[i]);
+ }
+ }
+
+ /**
+ * @see org.apache.bcel.classfile.Visitor#visitField(org.apache.bcel.classfile.Field)
+ */
+ public void visitField(Field f) {
+ String type = Utility.methodSignatureReturnType(f.getSignature());
+ log(" field type=" + type, Project.MSG_VERBOSE);
+ design.checkClass(type);
+
+ }
+
+ /**
+ * @see org.apache.bcel.classfile.Visitor#visitLocalVariable(org.apache.bcel.classfile.LocalVariable)
+ */
+ public void visitLocalVariable(LocalVariable v) {
+ String type = Utility.methodSignatureReturnType(v.getSignature());
+ log(" localVar type=" + type, Project.MSG_VERBOSE);
+ design.checkClass(type);
+ }
+
+ /**
+ * @see org.apache.bcel.classfile.Visitor#visitMethod(org.apache.bcel.classfile.Method)
+ */
+ public void visitMethod(Method m) {
+ log(" method=" + m.getName(), Project.MSG_VERBOSE);
+ String retType = Utility.methodSignatureReturnType(m.getSignature());
+ log(" method ret type=" + retType, Project.MSG_VERBOSE);
+ if (!"void".equals(retType))
+ design.checkClass(retType);
+
+ String[] types = Utility.methodSignatureArgumentTypes(m.getSignature());
+ for (int i = 0; i < types.length; i++) {
+ log(" method param[" + i + "]=" + types[i],
+ Project.MSG_VERBOSE);
+ design.checkClass(types[i]);
+ }
+
+ ExceptionTable excs = m.getExceptionTable();
+ if (excs != null) {
+ types = excs.getExceptionNames();
+ for (int i = 0; i < types.length; i++) {
+ log(" exc=" + types[i], Project.MSG_VERBOSE);
+ design.checkClass(types[i]);
+ }
+ }
+
+ processInstructions(m);
+ }
+
+ private void processInstructions(Method m) {
+ MethodGen mg = new MethodGen(m, design.getCurrentClass(), poolGen);
+
+ if (!mg.isAbstract() && !mg.isNative()) {
+ InstructionHandle ih = mg.getInstructionList().getStart();
+ for (; ih != null; ih = ih.getNext()) {
+ Instruction i = ih.getInstruction();
+ log(" instr=" + i, Project.MSG_DEBUG);
+ // if (i instanceof BranchInstruction) {
+ // branch_map.put(i, ih); // memorize container
+ // }
+
+ // if (ih.hasTargeters()) {
+ // if (i instanceof BranchInstruction) {
+ // _out.println(" InstructionHandle ih_"
+ // + ih.getPosition() + ";");
+ // } else {
+ // _out.print(" InstructionHandle ih_"
+ // + ih.getPosition() + " = ");
+ // }
+ // } else {
+ // _out.print(" ");
+ // }
+
+ // if (!visitInstruction(i))
+ i.accept(visitor);
+ }
+
+ // CodeExceptionGen[] handlers = mg.getExceptionHandlers();
+ //
+ // log("handlers len="+handlers.length, Project.MSG_DEBUG);
+ // for (int i = 0; i < handlers.length; i++) {
+ // CodeExceptionGen h = handlers[i];
+ // ObjectType t = h.getCatchType();
+ // log("type="+t, Project.MSG_DEBUG);
+ // if(t != null) {
+ // log("type="+t.getClassName(), Project.MSG_DEBUG);
+ // }
+ // }
+ // updateExceptionHandlers();
+ }
+ }
+
+ public void visitCodeException(CodeException c) {
+ String s = c.toString(pool, false);
+
+ int catch_type = c.getCatchType();
+
+ if (catch_type == 0)
+ return;
+
+ String temp = pool.getConstantString(catch_type,
+ Constants.CONSTANT_Class);
+ String str = Utility.compactClassName(temp, false);
+
+ log(" catch=" + str, Project.MSG_DEBUG);
+ design.checkClass(str);
+ }
+
+ //
+ public void visitCode(Code c) {
+ LineNumberTable table = c.getLineNumberTable();
+ // LocalVariableTable table = c.getLocalVariableTable();
+ if (table == null)
+ throw new BuildException(getNoDebugMsg(design.getCurrentClass()), location);
+ }
+
+ public static String getNoDebugMsg(String className) {
+ String s = "Class="+className+" was not compiled with the debug option(-g) and\n" +
+ "therefore verifydesign cannot be used on this jar. Please compile your code\n"+
+ "with -g option in javac or debug=\"true\" in the ant build.xml file";
+ return s;
+ }
+
+ /**
+ * @param jarName
+ * @return
+ */
+ public static String getNoFileMsg(File jarName) {
+ String s = "File you specified in your path(or jar attribute)='"+jarName.getAbsolutePath()+"' does not exist";
+ return s;
+ }
+
+
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/inifile/IniFile.java b/src/java/net/sf/antcontrib/inifile/IniFile.java
new file mode 100644
index 0000000..b65044a
--- /dev/null
+++ b/src/java/net/sf/antcontrib/inifile/IniFile.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.inifile;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.*;
+
+
+/****************************************************************************
+ * Class representing a windows style .ini file.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+public class IniFile
+{
+ private List sections;
+ private Map sectionMap;
+
+ /***
+ * Create a new IniFile object
+ */
+ public IniFile()
+ {
+ super();
+ this.sections = new ArrayList();
+ this.sectionMap = new HashMap();
+ }
+
+ /***
+ * Gets the List of IniSection objects contained in this IniFile
+ * @return a List of IniSection objects
+ */
+ public List getSections()
+ {
+ return sections;
+ }
+
+
+ /***
+ * Gets the IniSection with the given name
+ * @param name the name of the section
+ */
+ public IniSection getSection(String name)
+ {
+ return (IniSection)sectionMap.get(name);
+ }
+
+ /***
+ * Sets an IniSection object. If a section with the given
+ * name already exists, it is replaced with the passed in section.
+ * @param section The section to set.
+ */
+ public void setSection(IniSection section)
+ {
+ IniSection sec = (IniSection)sectionMap.get(section.getName());
+ if (sec != null)
+ {
+ int idx = sections.indexOf(sec);
+ sections.set(idx, section);
+ }
+ else
+ {
+ sections.add(section);
+ }
+
+ sectionMap.put(section.getName(), section);
+ }
+
+ /***
+ * Removes an entire section from the IniFile
+ * @param name The name of the section to remove
+ */
+ public void removeSection(String name)
+ {
+ IniSection sec = (IniSection)sectionMap.get(name);
+ if (sec != null)
+ {
+ int idx = sections.indexOf(sec);
+ sections.remove(idx);
+ sectionMap.remove(name);
+ }
+ }
+
+ /***
+ * Gets a named property from a specific section
+ * @param section The name of the section
+ * @param property The name of the property
+ * @return The property value, or null, if either the section or property
+ * does not exist.
+ */
+ public String getProperty(String section, String property)
+ {
+ String value = null;
+ IniSection sec = getSection(section);
+ if (sec != null)
+ {
+ IniProperty prop = sec.getProperty(property);
+ if (prop != null)
+ {
+ value = prop.getValue();
+ }
+ }
+ return value;
+ }
+
+ /***
+ * Sets the value of a property in a given section. If the section does
+ * not exist, it is automatically created.
+ * @param section The name of the section
+ * @param property The name of the property
+ * @param value The value of the property
+ */
+ public void setProperty(String section, String property, String value)
+ {
+ IniSection sec = getSection(section);
+ if (sec == null)
+ {
+ sec = new IniSection(section);
+ setSection(sec);
+ }
+
+ sec.setProperty(new IniProperty(property, value));
+ }
+
+ /***
+ * Removes a property from a section.
+ * @param section The name of the section
+ * @param property The name of the property
+ */
+ public void removeProperty(String section, String property)
+ {
+ IniSection sec = getSection(section);
+ if (sec != null)
+ {
+ sec.removeProperty(property);
+ }
+ }
+
+ /***
+ * Writes the current iniFile instance to a Writer object for
+ * serialization.
+ * @param writer The writer to write to
+ * @throws IOException
+ */
+ public void write(Writer writer)
+ throws IOException
+ {
+ Iterator it = sections.iterator();
+ IniSection section = null;
+ while (it.hasNext())
+ {
+ section = (IniSection)it.next();
+ section.write(writer);
+ writer.write(System.getProperty("line.separator"));
+ }
+ }
+
+ /***
+ * Reads from a Reader into the current IniFile instance. Reading
+ * appends to the current instance, so if the current instance has
+ * properties, those properties will still exist.
+ * @param reader The reader to read from.
+ * @throws IOException
+ */
+ public void read(Reader reader)
+ throws IOException
+ {
+ BufferedReader br = new BufferedReader(reader);
+ String line = null;
+
+ IniSection currentSection = new IniSection("NONE");
+
+ while ((line = br.readLine()) != null)
+ {
+ int pos = line.indexOf('#');
+ if (pos != -1)
+ line = line.substring(0,pos);
+
+ pos = line.indexOf(';');
+ if (pos != -1)
+ line = line.substring(0,pos);
+
+ line = line.trim();
+ if (line.length() > 0)
+ {
+ if(line.startsWith("[") && line.endsWith("]"))
+ {
+ String secName = line.substring(1, line.length()-1);
+ currentSection = getSection(secName);
+ if (currentSection == null)
+ {
+ currentSection = new IniSection(secName);
+ setSection(currentSection);
+ }
+ }
+ else
+ {
+ String name = line;
+ String value = "";
+ pos = line.indexOf("=");
+ if (pos != -1)
+ {
+ name = line.substring(0,pos);
+ value = line.substring(pos+1);
+ }
+
+ currentSection.setProperty(new IniProperty(name,value));
+ }
+ }
+
+
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/inifile/IniFileTask.java b/src/java/net/sf/antcontrib/inifile/IniFileTask.java
new file mode 100644
index 0000000..d7e44aa
--- /dev/null
+++ b/src/java/net/sf/antcontrib/inifile/IniFileTask.java
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.inifile;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class IniFileTask
+ extends Task
+{
+ public static abstract class IniOperation
+ {
+ private String section;
+ private String property;
+ private String ifCond;
+ private String unlessCond;
+
+ public IniOperation()
+ {
+ super();
+ }
+
+ public String getSection()
+ {
+ return section;
+ }
+
+
+ public void setSection(String section)
+ {
+ this.section = section;
+ }
+
+
+ public String getProperty()
+ {
+ return property;
+ }
+
+
+ public void setProperty(String property)
+ {
+ this.property = property;
+ }
+
+
+ public void setIf(String ifCond)
+ {
+ this.ifCond = ifCond;
+ }
+
+ public void setUnless(String unlessCond)
+ {
+ this.unlessCond = unlessCond;
+ }
+
+ /**
+ * Returns true if the define's if and unless conditions
+ * (if any) are satisfied.
+ */
+ public boolean isActive(org.apache.tools.ant.Project p)
+ {
+ if (ifCond != null && p.getProperty(ifCond) == null)
+ {
+ return false;
+ }
+ else if (unlessCond != null && p.getProperty(unlessCond) != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public void execute(Project project, IniFile iniFile)
+ {
+ if (isActive(project))
+ operate(iniFile);
+ }
+
+ protected abstract void operate(IniFile file);
+ }
+
+ public static final class Remove
+ extends IniOperation
+ {
+ public Remove()
+ {
+ super();
+ }
+
+ protected void operate(IniFile file)
+ {
+ String secName = getSection();
+ String propName = getProperty();
+
+ if (propName == null)
+ {
+ file.removeSection(secName);
+ }
+ else
+ {
+ IniSection section = file.getSection(secName);
+ if (section != null)
+ section.removeProperty(propName);
+ }
+ }
+ }
+
+
+ public final class Set
+ extends IniOperation
+ {
+ private String value;
+ private String operation;
+
+ public Set()
+ {
+ super();
+ }
+
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+
+ public void setOperation(String operation)
+ {
+ this.operation = operation;
+ }
+
+
+ protected void operate(IniFile file)
+ {
+ String secName = getSection();
+ String propName = getProperty();
+
+ IniSection section = file.getSection(secName);
+ if (section == null)
+ {
+ section = new IniSection(secName);
+ file.setSection(section);
+ }
+
+ if (propName != null)
+ {
+ if (operation != null)
+ {
+ if ("+".equals(operation))
+ {
+ IniProperty prop = section.getProperty(propName);
+ value = prop.getValue();
+ int intVal = Integer.parseInt(value) + 1;
+ value = String.valueOf(intVal);
+ }
+ else if ("-".equals(operation))
+ {
+ IniProperty prop = section.getProperty(propName);
+ value = prop.getValue();
+ int intVal = Integer.parseInt(value) - 1;
+ value = String.valueOf(intVal);
+ }
+ }
+ section.setProperty(new IniProperty(propName, value));
+ }
+ }
+
+ }
+
+ private File source;
+ private File dest;
+ private Vector operations;
+
+ public IniFileTask()
+ {
+ super();
+ this.operations = new Vector();
+ }
+
+ public Set createSet()
+ {
+ Set set = new Set();
+ operations.add(set);
+ return set;
+ }
+
+ public Remove createRemove()
+ {
+ Remove remove = new Remove();
+ operations.add(remove);
+ return remove;
+ }
+
+
+ public void setSource(File source)
+ {
+ this.source = source;
+ }
+
+
+ public void setDest(File dest)
+ {
+ this.dest = dest;
+ }
+
+
+ public void execute()
+ throws BuildException
+ {
+ if (dest == null)
+ throw new BuildException("You must supply a dest file to write to.");
+
+ IniFile iniFile = null;
+
+ try
+ {
+ iniFile = readIniFile(source);
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+
+ Iterator it = operations.iterator();
+ IniOperation operation = null;
+ while (it.hasNext())
+ {
+ operation = (IniOperation)it.next();
+ operation.execute(getProject(), iniFile);
+ }
+
+ FileWriter writer = null;
+
+ try
+ {
+ try
+ {
+ writer = new FileWriter(dest);
+ iniFile.write(writer);
+ }
+ finally
+ {
+ try
+ {
+ if (writer != null)
+ writer.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+
+ }
+
+
+ private IniFile readIniFile(File source)
+ throws IOException
+ {
+ FileReader reader = null;
+ IniFile iniFile = new IniFile();
+
+ if (source == null)
+ return iniFile;
+
+ try
+ {
+ reader = new FileReader(source);
+ iniFile.read(reader);
+ }
+ finally
+ {
+ try
+ {
+ if (reader != null)
+ reader.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ }
+
+ return iniFile;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/inifile/IniPart.java b/src/java/net/sf/antcontrib/inifile/IniPart.java
new file mode 100644
index 0000000..b7e07f1
--- /dev/null
+++ b/src/java/net/sf/antcontrib/inifile/IniPart.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.inifile;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+/****************************************************************************
+ * A part of an IniFile that might be written to disk.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ ****************************************************************************/
+
+
+public interface IniPart
+{
+ /***
+ * Write this part of the IniFile to a writer
+ * @param writer The writer to write to
+ */
+ public void write(Writer writer)
+ throws IOException;
+}
diff --git a/src/java/net/sf/antcontrib/inifile/IniProperty.java b/src/java/net/sf/antcontrib/inifile/IniProperty.java
new file mode 100644
index 0000000..49a61af
--- /dev/null
+++ b/src/java/net/sf/antcontrib/inifile/IniProperty.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.inifile;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+/****************************************************************************
+ * A single property in an IniSection.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class IniProperty
+ implements IniPart
+{
+ private String name;
+ private String value;
+
+ /***
+ * Default constructor
+ */
+ public IniProperty()
+ {
+ super();
+ }
+
+ /***
+ * Construct an IniProperty with a certain name and value
+ * @param name The name of the property
+ * @param value The property value
+ */
+ public IniProperty(String name, String value)
+ {
+ this();
+ this.name = name;
+ this.value = value;
+ }
+
+ /***
+ * Gets the name of the property
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+ /***
+ * Sets the name of the property
+ * @param name The name of the property
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+
+ /***
+ * Gets the value of the property
+ */
+ public String getValue()
+ {
+ return value;
+ }
+
+
+ /***
+ * Sets the value of the property
+ * @param value the value of the property
+ */
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+
+ /***
+ * Write this property to a writer object.
+ * @param writer
+ * @throws IOException
+ */
+ public void write(Writer writer)
+ throws IOException
+ {
+ writer.write(name);
+ if (! name.trim().startsWith(";"))
+ writer.write("=" + value);
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/inifile/IniSection.java b/src/java/net/sf/antcontrib/inifile/IniSection.java
new file mode 100644
index 0000000..da98859
--- /dev/null
+++ b/src/java/net/sf/antcontrib/inifile/IniSection.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.inifile;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.*;
+
+
+/****************************************************************************
+ * A section within an IniFile.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class IniSection
+ implements IniPart
+{
+ private String name;
+ private List properties;
+ private Map propertyMap;
+
+ /***
+ * Default contructor, constructs an IniSectino with no name
+ */
+ public IniSection()
+ {
+ super();
+ this.propertyMap = new HashMap();
+ this.properties = new ArrayList();
+ }
+
+
+ /***
+ * Constructs an IniSection with the given name
+ * @param name The name of the section
+ */
+ public IniSection(String name)
+ {
+ this();
+ this.name = name;
+ }
+
+
+ /***
+ * Gets a list of all properties in this section
+ * @return A List of IniProperty objects
+ */
+ public List getProperties()
+ {
+ return properties;
+ }
+
+
+ /***
+ * Gets the name of the section
+ */
+ public String getName()
+ {
+ return name;
+ }
+
+
+ /***
+ * Sets the name of the section
+ * @param name The name of the section
+ */
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ /***
+ * Gets the property with the given name
+ * @param name The name of the property
+ */
+ public IniProperty getProperty(String name)
+ {
+ return (IniProperty)propertyMap.get(name);
+ }
+
+ /***
+ * Sets a property, replacing the old value, if necessary.
+ * @param property The property to set
+ */
+ public void setProperty(IniProperty property)
+ {
+ IniProperty prop = (IniProperty)propertyMap.get(property.getName());
+ if (prop != null)
+ {
+ int idx = properties.indexOf(prop);
+ properties.set(idx, property);
+ }
+ else
+ {
+ properties.add(property);
+ }
+
+ propertyMap.put(property.getName(), property);
+ }
+
+ /***
+ * Removes a property from this ection
+ * @param name The name of the property to remove
+ */
+ public void removeProperty(String name)
+ {
+ IniProperty prop = (IniProperty)propertyMap.get(name);
+ if (prop != null)
+ {
+ int idx = properties.indexOf(prop);
+ properties.remove(idx);
+ propertyMap.remove(name);
+ }
+ }
+
+
+ public void write(Writer writer)
+ throws IOException
+ {
+ writer.write("[" + name + "]");
+ writer.write(System.getProperty("line.separator"));
+ Iterator it = properties.iterator();
+ IniProperty prop = null;
+ while (it.hasNext())
+ {
+ prop = (IniProperty)it.next();
+ prop.write(writer);
+ writer.write(System.getProperty("line.separator"));
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/input/GUIInputHandler.java b/src/java/net/sf/antcontrib/input/GUIInputHandler.java
new file mode 100644
index 0000000..82f7abe
--- /dev/null
+++ b/src/java/net/sf/antcontrib/input/GUIInputHandler.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.input;
+
+import java.awt.*;
+import javax.swing.*;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.input.InputHandler;
+import org.apache.tools.ant.input.InputRequest;
+import org.apache.tools.ant.input.MultipleChoiceInputRequest;
+
+/**
+ * Prompts for user input using a JOptionPane. Developed for use with
+ * Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author <a href="mailto:[email protected]">Dale Anson</a>
+ * @version $Revision: 1.3 $
+ * @since Ant 1.5
+ */
+public class GUIInputHandler implements InputHandler {
+
+ private Component parent = null;
+
+ public GUIInputHandler() {}
+
+ /**
+ * @param parent the parent component to display the input dialog.
+ */
+ public GUIInputHandler( Component parent ) {
+ this.parent = parent;
+ }
+
+ /**
+ * Prompts and requests input. May loop until a valid input has
+ * been entered.
+ */
+ public void handleInput( InputRequest request ) throws BuildException {
+
+ if ( request instanceof MultipleChoiceInputRequest ) {
+ String prompt = request.getPrompt();
+ String title = "Select Input";
+ int optionType = JOptionPane.YES_NO_OPTION;
+ int messageType = JOptionPane.QUESTION_MESSAGE;
+ Icon icon = null;
+ Object[] choices = ( ( MultipleChoiceInputRequest ) request ).getChoices().toArray();
+ Object initialChoice = null;
+ do {
+ Object input = JOptionPane.showInputDialog(parent, prompt,
+ title, optionType, icon, choices, initialChoice);
+ if (input == null)
+ throw new BuildException("User cancelled.");
+ request.setInput(input.toString());
+ } while (!request.isInputValid());
+
+ }
+ else {
+ do {
+ String input = JOptionPane.showInputDialog( parent, request.getPrompt() );
+ request.setInput( input );
+ } while ( !request.isInputValid() );
+ }
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/logic/AntCallBack.java b/src/java/net/sf/antcontrib/logic/AntCallBack.java
new file mode 100644
index 0000000..cbd09dc
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/AntCallBack.java
@@ -0,0 +1,644 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.tools.ant.*;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ * Identical (copy and paste, even) to the 'Ant' task, with the exception that
+ * properties from the new project can be copied back into the original project.
+ * Further modified to emulate "antcall". Build a sub-project. <pre>
+ * &lt;target name=&quot;foo&quot; depends=&quot;init&quot;&gt;
+ * &lt;ant antfile=&quot;build.xml&quot; target=&quot;bar&quot; &gt;
+ * &lt;property name=&quot;property1&quot; value=&quot;aaaaa&quot; /&gt;
+ * &lt;property name=&quot;foo&quot; value=&quot;baz&quot; /&gt;
+ * &lt;/ant&gt;</SPAN> &lt;/target&gt;</SPAN> &lt;target name=&quot;bar&quot;
+ * depends=&quot;init&quot;&gt; &lt;echo message=&quot;prop is ${property1}
+ * ${foo}&quot; /&gt; &lt;/target&gt; </pre>
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ * <p>Credit to Costin for the original &lt;ant&gt; task, on which this is based.
+ *
+ * @author [email protected]
+ * @author Dale Anson, [email protected]
+ * @since Ant 1.1
+ * @ant.task category="control"
+ */
+public class AntCallBack extends Task {
+
+ /** the basedir where is executed the build file */
+ private File dir = null;
+
+ /**
+ * the build.xml file (can be absolute) in this case dir will be ignored
+ */
+ private String antFile = null;
+
+ /** the target to call if any */
+ private String target = null;
+
+ /** the output */
+ private String output = null;
+
+ /** should we inherit properties from the parent ? */
+ private boolean inheritAll = true;
+
+ /** should we inherit references from the parent ? */
+ private boolean inheritRefs = false;
+
+ /** the properties to pass to the new project */
+ private Vector properties = new Vector();
+
+ /** the references to pass to the new project */
+ private Vector references = new Vector();
+
+ /** the temporary project created to run the build file */
+ private Project newProject;
+
+ /** The stream to which output is to be written. */
+ private PrintStream out = null;
+
+ /** the name of the property to fetch from the new project */
+ private String returnName = null;
+
+
+ /**
+ * If true, pass all properties to the new Ant project. Defaults to true.
+ *
+ * @param value The new inheritAll value
+ */
+ public void setInheritAll( boolean value ) {
+ inheritAll = value;
+ }
+
+
+ /**
+ * If true, pass all references to the new Ant project. Defaults to false.
+ *
+ * @param value The new inheritRefs value
+ */
+ public void setInheritRefs( boolean value ) {
+ inheritRefs = value;
+ }
+
+
+ /** Creates a Project instance for the project to call. */
+ public void init() {
+ newProject = new Project();
+ newProject.setJavaVersionProperty();
+ newProject.addTaskDefinition( "property",
+ (Class)getProject().getTaskDefinitions()
+ .get( "property" ) );
+ }
+
+
+ /**
+ * Called in execute or createProperty if newProject is null. <p>
+ *
+ * This can happen if the same instance of this task is run twice as
+ * newProject is set to null at the end of execute (to save memory and help
+ * the GC).</p> <p>
+ *
+ * Sets all properties that have been defined as nested property elements.
+ * </p>
+ */
+ private void reinit() {
+ init();
+ final int count = properties.size();
+ for ( int i = 0; i < count; i++ ) {
+ Property p = (Property)properties.elementAt( i );
+ Property newP = (Property)newProject.createTask( "property" );
+ newP.setName( p.getName() );
+ if ( p.getValue() != null ) {
+ newP.setValue( p.getValue() );
+ }
+ if ( p.getFile() != null ) {
+ newP.setFile( p.getFile() );
+ }
+ if ( p.getResource() != null ) {
+ newP.setResource( p.getResource() );
+ }
+ if ( p.getPrefix() != null ) {
+ newP.setPrefix( p.getPrefix() );
+ }
+ if ( p.getRefid() != null ) {
+ newP.setRefid( p.getRefid() );
+ }
+ if ( p.getEnvironment() != null ) {
+ newP.setEnvironment( p.getEnvironment() );
+ }
+ if ( p.getClasspath() != null ) {
+ newP.setClasspath( p.getClasspath() );
+ }
+ properties.setElementAt( newP, i );
+ }
+ }
+
+
+ /**
+ * Attaches the build listeners of the current project to the new project,
+ * configures a possible logfile, transfers task and data-type definitions,
+ * transfers properties (either all or just the ones specified as user
+ * properties to the current project, depending on inheritall), transfers the
+ * input handler.
+ */
+ private void initializeProject() {
+ newProject.setInputHandler( getProject().getInputHandler() );
+
+ Vector listeners = getProject().getBuildListeners();
+ final int count = listeners.size();
+ for ( int i = 0; i < count; i++ ) {
+ newProject.addBuildListener( (BuildListener)listeners.elementAt( i ) );
+ }
+
+ if ( output != null ) {
+ File outfile = null;
+ if ( dir != null ) {
+ outfile = FileUtils.newFileUtils().resolveFile( dir, output );
+ }
+ else {
+ outfile = getProject().resolveFile( output );
+ }
+ try {
+ out = new PrintStream( new FileOutputStream( outfile ) );
+ DefaultLogger logger = new DefaultLogger();
+ logger.setMessageOutputLevel( Project.MSG_INFO );
+ logger.setOutputPrintStream( out );
+ logger.setErrorPrintStream( out );
+ newProject.addBuildListener( logger );
+ }
+ catch ( IOException ex ) {
+ log( "Ant: Can't set output to " + output );
+ }
+ }
+
+ Hashtable taskdefs = getProject().getTaskDefinitions();
+ Enumeration et = taskdefs.keys();
+ while ( et.hasMoreElements() ) {
+ String taskName = (String)et.nextElement();
+ if ( taskName.equals( "property" ) ) {
+ // we have already added this taskdef in #init
+ continue;
+ }
+ Class taskClass = (Class)taskdefs.get( taskName );
+ newProject.addTaskDefinition( taskName, taskClass );
+ }
+
+ Hashtable typedefs = getProject().getDataTypeDefinitions();
+ Enumeration e = typedefs.keys();
+ while ( e.hasMoreElements() ) {
+ String typeName = (String)e.nextElement();
+ Class typeClass = (Class)typedefs.get( typeName );
+ newProject.addDataTypeDefinition( typeName, typeClass );
+ }
+
+ // set user-defined properties
+ getProject().copyUserProperties( newProject );
+
+ if ( !inheritAll ) {
+ // set Java built-in properties separately,
+ // b/c we won't inherit them.
+ newProject.setSystemProperties();
+
+ }
+ else {
+ // set all properties from calling project
+
+ Hashtable props = getProject().getProperties();
+ e = props.keys();
+ while ( e.hasMoreElements() ) {
+ String arg = e.nextElement().toString();
+ if ( "basedir".equals( arg ) || "ant.file".equals( arg ) ) {
+ // basedir and ant.file get special treatment in execute()
+ continue;
+ }
+
+ String value = props.get( arg ).toString();
+ // don't re-set user properties, avoid the warning message
+ if ( newProject.getProperty( arg ) == null ) {
+ // no user property
+ newProject.setNewProperty( arg, value );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Pass output sent to System.out to the new project.
+ *
+ * @param line Description of the Parameter
+ * @since Ant 1.5
+ */
+ protected void handleOutput( String line ) {
+ if ( newProject != null ) {
+ newProject.demuxOutput( line, false );
+ }
+ else {
+ super.handleOutput( line );
+ }
+ }
+
+
+ /**
+ * Pass output sent to System.err to the new project.
+ *
+ * @param line Description of the Parameter
+ * @since Ant 1.5
+ */
+ protected void handleErrorOutput( String line ) {
+ if ( newProject != null ) {
+ newProject.demuxOutput( line, true );
+ }
+ else {
+ super.handleErrorOutput( line );
+ }
+ }
+
+
+ /**
+ * Do the execution.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ public void execute() throws BuildException {
+ setAntfile( getProject().getProperty( "ant.file" ) );
+
+ File savedDir = dir;
+ String savedAntFile = antFile;
+ String savedTarget = target;
+ try {
+ if ( newProject == null ) {
+ reinit();
+ }
+
+ if ( ( dir == null ) && ( inheritAll ) ) {
+ dir = getProject().getBaseDir();
+ }
+
+ initializeProject();
+
+ if ( dir != null ) {
+ newProject.setBaseDir( dir );
+ if ( savedDir != null ) { // has been set explicitly
+ newProject.setInheritedProperty( "basedir",
+ dir.getAbsolutePath() );
+ }
+ }
+ else {
+ dir = getProject().getBaseDir();
+ }
+
+ overrideProperties();
+
+ if ( antFile == null ) {
+ throw new BuildException( "Attribute target is required.",
+ getLocation() );
+ //antFile = "build.xml";
+ }
+
+ File file = FileUtils.newFileUtils().resolveFile( dir, antFile );
+ antFile = file.getAbsolutePath();
+
+ log( "calling target " + ( target != null ? target : "[default]" )
+ + " in build file " + antFile.toString(),
+ Project.MSG_VERBOSE );
+ newProject.setUserProperty( "ant.file", antFile );
+ ProjectHelper.configureProject( newProject, new File( antFile ) );
+
+ if ( target == null ) {
+ target = newProject.getDefaultTarget();
+ }
+
+ addReferences();
+
+ // Are we trying to call the target in which we are defined?
+ if ( newProject.getBaseDir().equals( getProject().getBaseDir() ) &&
+ newProject.getProperty( "ant.file" ).equals( getProject().getProperty( "ant.file" ) ) &&
+ getOwningTarget() != null &&
+ target.equals( this.getOwningTarget().getName() ) ) {
+
+ throw new BuildException( "antcallback task calling its own parent "
+ + "target" );
+ }
+
+ newProject.executeTarget( target );
+
+ // copy back the props if possible
+ if ( returnName != null ) {
+ StringTokenizer st = new StringTokenizer( returnName, "," );
+ while ( st.hasMoreTokens() ) {
+ String name = st.nextToken().trim();
+ String value = newProject.getUserProperty( name );
+ if ( value != null ) {
+ getProject().setUserProperty( name, value );
+ }
+ else {
+ value = newProject.getProperty( name );
+ if ( value != null ) {
+ getProject().setProperty( name, value );
+ }
+ }
+ }
+ }
+ }
+ finally {
+ // help the gc
+ newProject = null;
+ if ( output != null && out != null ) {
+ try {
+ out.close();
+ }
+ catch ( final Exception e ) {
+ //ignore
+ }
+ }
+ dir = savedDir;
+ antFile = savedAntFile;
+ target = savedTarget;
+ }
+ }
+
+
+ /**
+ * Override the properties in the new project with the one explicitly defined
+ * as nested elements here.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ private void overrideProperties() throws BuildException {
+ Enumeration e = properties.elements();
+ while ( e.hasMoreElements() ) {
+ Property p = (Property)e.nextElement();
+ p.setProject( newProject );
+ p.execute();
+ }
+ getProject().copyInheritedProperties( newProject );
+ }
+
+
+ /**
+ * Add the references explicitly defined as nested elements to the new
+ * project. Also copy over all references that don't override existing
+ * references in the new project if inheritrefs has been requested.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ private void addReferences() throws BuildException {
+ Hashtable thisReferences = (Hashtable)getProject().getReferences().clone();
+ Hashtable newReferences = newProject.getReferences();
+ Enumeration e;
+ if ( references.size() > 0 ) {
+ for ( e = references.elements(); e.hasMoreElements(); ) {
+ Reference ref = (Reference)e.nextElement();
+ String refid = ref.getRefId();
+ if ( refid == null ) {
+ throw new BuildException( "the refid attribute is required"
+ + " for reference elements" );
+ }
+ if ( !thisReferences.containsKey( refid ) ) {
+ log( "Parent project doesn't contain any reference '"
+ + refid + "'",
+ Project.MSG_WARN );
+ continue;
+ }
+
+ thisReferences.remove( refid );
+ String toRefid = ref.getToRefid();
+ if ( toRefid == null ) {
+ toRefid = refid;
+ }
+ copyReference( refid, toRefid );
+ }
+ }
+
+ // Now add all references that are not defined in the
+ // subproject, if inheritRefs is true
+ if ( inheritRefs ) {
+ for ( e = thisReferences.keys(); e.hasMoreElements(); ) {
+ String key = (String)e.nextElement();
+ if ( newReferences.containsKey( key ) ) {
+ continue;
+ }
+ copyReference( key, key );
+ }
+ }
+ }
+
+
+ /**
+ * Try to clone and reconfigure the object referenced by oldkey in the parent
+ * project and add it to the new project with the key newkey. <p>
+ *
+ * If we cannot clone it, copy the referenced object itself and keep our
+ * fingers crossed.</p>
+ *
+ * @param oldKey Description of the Parameter
+ * @param newKey Description of the Parameter
+ */
+ private void copyReference( String oldKey, String newKey ) {
+ Object orig = getProject().getReference( oldKey );
+ Class c = orig.getClass();
+ Object copy = orig;
+ try {
+ Method cloneM = c.getMethod( "clone", new Class[0] );
+ if ( cloneM != null ) {
+ copy = cloneM.invoke( orig, new Object[0] );
+ }
+ }
+ catch ( Exception e ) {
+ // not Clonable
+ }
+
+ if ( copy instanceof ProjectComponent ) {
+ ( (ProjectComponent)copy ).setProject( newProject );
+ }
+ else {
+ try {
+ Method setProjectM =
+ c.getMethod( "setProject", new Class[]{Project.class} );
+ if ( setProjectM != null ) {
+ setProjectM.invoke( copy, new Object[]{newProject} );
+ }
+ }
+ catch ( NoSuchMethodException e ) {
+ // ignore this if the class being referenced does not have
+ // a set project method.
+ }
+ catch ( Exception e2 ) {
+ String msg = "Error setting new project instance for "
+ + "reference with id " + oldKey;
+ throw new BuildException( msg, e2, getLocation() );
+ }
+ }
+ newProject.addReference( newKey, copy );
+ }
+
+
+ /**
+ * The directory to use as a base directory for the new Ant project. Defaults
+ * to the current project's basedir, unless inheritall has been set to false,
+ * in which case it doesn't have a default value. This will override the
+ * basedir setting of the called project.
+ *
+ * @param d The new dir value
+ */
+ public void setDir( File d ) {
+ this.dir = d;
+ }
+
+
+ /**
+ * The build file to use. Defaults to "build.xml". This file is expected to
+ * be a filename relative to the dir attribute given.
+ *
+ * @param s The new antfile value
+ */
+ 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;
+ }
+
+
+ /**
+ * The target of the new Ant project to execute. Defaults to the new
+ * project's default target.
+ *
+ * @param s The new target value
+ */
+ public void setTarget( String s ) {
+ this.target = s;
+ }
+
+
+ /**
+ * Filename to write the output to. This is relative to the value of the dir
+ * attribute if it has been set or to the base directory of the current
+ * project otherwise.
+ *
+ * @param s The new output value
+ */
+ public void setOutput( String s ) {
+ this.output = s;
+ }
+
+
+ /**
+ * Property to pass to the new project. The property is passed as a 'user
+ * property'
+ *
+ * @return Description of the Return Value
+ */
+ public Property createProperty() {
+ if ( newProject == null ) {
+ reinit();
+ }
+ /*
+ * Property p = new Property( true, getProject() );
+ */
+ Property p = new Property();
+ p.setProject( newProject );
+ p.setTaskName( "property" );
+ properties.addElement( p );
+ return p;
+ }
+
+
+ /**
+ * Property to pass to the invoked target.
+ */
+ public Property createParam() {
+ return createProperty();
+ }
+
+ /**
+ * Set the property or properties that are set in the new project to be
+ * transfered back to the original project. As with all properties, if the
+ * property already exists in the original project, it will not be overridden
+ * by a different value from the new project.
+ *
+ * @param r the name of a property in the new project to set in the original
+ * project. This may be a comma separate list of properties.
+ */
+ public void setReturn( String r ) {
+ returnName = r;
+ }
+
+
+ /**
+ * Reference element identifying a data type to carry over to the new
+ * project.
+ *
+ * @param r The feature to be added to the Reference attribute
+ */
+ public void addReference( Reference r ) {
+ references.addElement( r );
+ }
+
+
+ /**
+ * Helper class that implements the nested &lt;reference&gt; element of
+ * &lt;ant&gt; and &lt;antcall&gt;.
+ *
+ * @author danson
+ */
+ public static class Reference
+ extends org.apache.tools.ant.types.Reference {
+
+ /** Creates a reference to be configured by Ant */
+ public Reference() {
+ super();
+ }
+
+
+ private String targetid = null;
+
+
+ /**
+ * Set the id that this reference to be stored under in the new project.
+ *
+ * @param targetid the id under which this reference will be passed to
+ * the new project
+ */
+ public void setToRefid( String targetid ) {
+ this.targetid = targetid;
+ }
+
+
+ /**
+ * Get the id under which this reference will be stored in the new project
+ *
+ * @return the id of the reference in the new project.
+ */
+ public String getToRefid() {
+ return targetid;
+ }
+ }
+}
+
diff --git a/src/java/net/sf/antcontrib/logic/AntFetch.java b/src/java/net/sf/antcontrib/logic/AntFetch.java
new file mode 100644
index 0000000..fa2b13f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/AntFetch.java
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.DefaultLogger;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ * Identical (copy and paste, even) to the 'Ant' task, with the exception that
+ * properties from the new project can be copied back into the original project.
+ * Build a sub-project. <pre>
+ * &lt;target name=&quot;foo&quot; depends=&quot;init&quot;&gt;
+ * &lt;ant antfile=&quot;build.xml&quot; target=&quot;bar&quot; &gt;
+ * &lt;property name=&quot;property1&quot; value=&quot;aaaaa&quot; /&gt;
+ * &lt;property name=&quot;foo&quot; value=&quot;baz&quot; /&gt;
+ * &lt;/ant&gt;</SPAN> &lt;/target&gt;</SPAN> &lt;target name=&quot;bar&quot;
+ * depends=&quot;init&quot;&gt; &lt;echo message=&quot;prop is ${property1}
+ * ${foo}&quot; /&gt; &lt;/target&gt; </pre>
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ * <p>Credit to Costin for the original &lt;ant&gt; task, on which this is based.
+ *
+ * @author [email protected]
+ * @author Dale Anson, [email protected]
+ * @since Ant 1.1
+ * @ant.task category="control"
+ */
+public class AntFetch extends Task {
+
+ /** the basedir where is executed the build file */
+ private File dir = null;
+
+ /**
+ * the build.xml file (can be absolute) in this case dir will be ignored
+ */
+ private String antFile = null;
+
+ /** the target to call if any */
+ private String target = null;
+
+ /** the output */
+ private String output = null;
+
+ /** should we inherit properties from the parent ? */
+ private boolean inheritAll = true;
+
+ /** should we inherit references from the parent ? */
+ private boolean inheritRefs = false;
+
+ /** the properties to pass to the new project */
+ private Vector properties = new Vector();
+
+ /** the references to pass to the new project */
+ private Vector references = new Vector();
+
+ /** the temporary project created to run the build file */
+ private Project newProject;
+
+ /** The stream to which output is to be written. */
+ private PrintStream out = null;
+
+ /** the name of the property to fetch from the new project */
+ private String returnName = null;
+
+
+ /**
+ * If true, pass all properties to the new Ant project. Defaults to true.
+ *
+ * @param value The new inheritAll value
+ */
+ public void setInheritAll( boolean value ) {
+ inheritAll = value;
+ }
+
+
+ /**
+ * If true, pass all references to the new Ant project. Defaults to false.
+ *
+ * @param value The new inheritRefs value
+ */
+ public void setInheritRefs( boolean value ) {
+ inheritRefs = value;
+ }
+
+
+ /** Creates a Project instance for the project to call. */
+ public void init() {
+ newProject = new Project();
+ newProject.setJavaVersionProperty();
+ newProject.addTaskDefinition( "property",
+ (Class)getProject().getTaskDefinitions()
+ .get( "property" ) );
+ }
+
+
+ /**
+ * Called in execute or createProperty if newProject is null. <p>
+ *
+ * This can happen if the same instance of this task is run twice as
+ * newProject is set to null at the end of execute (to save memory and help
+ * the GC).</p> <p>
+ *
+ * Sets all properties that have been defined as nested property elements.
+ * </p>
+ */
+ private void reinit() {
+ init();
+ final int count = properties.size();
+ for ( int i = 0; i < count; i++ ) {
+ Property p = (Property)properties.elementAt( i );
+ Property newP = (Property)newProject.createTask( "property" );
+ newP.setName( p.getName() );
+ if ( p.getValue() != null ) {
+ newP.setValue( p.getValue() );
+ }
+ if ( p.getFile() != null ) {
+ newP.setFile( p.getFile() );
+ }
+ if ( p.getResource() != null ) {
+ newP.setResource( p.getResource() );
+ }
+ if ( p.getPrefix() != null ) {
+ newP.setPrefix( p.getPrefix() );
+ }
+ if ( p.getRefid() != null ) {
+ newP.setRefid( p.getRefid() );
+ }
+ if ( p.getEnvironment() != null ) {
+ newP.setEnvironment( p.getEnvironment() );
+ }
+ if ( p.getClasspath() != null ) {
+ newP.setClasspath( p.getClasspath() );
+ }
+ properties.setElementAt( newP, i );
+ }
+ }
+
+
+ /**
+ * Attaches the build listeners of the current project to the new project,
+ * configures a possible logfile, transfers task and data-type definitions,
+ * transfers properties (either all or just the ones specified as user
+ * properties to the current project, depending on inheritall), transfers the
+ * input handler.
+ */
+ private void initializeProject() {
+ newProject.setInputHandler( getProject().getInputHandler() );
+
+ Vector listeners = getProject().getBuildListeners();
+ final int count = listeners.size();
+ for ( int i = 0; i < count; i++ ) {
+ newProject.addBuildListener( (BuildListener)listeners.elementAt( i ) );
+ }
+
+ if ( output != null ) {
+ File outfile = null;
+ if ( dir != null ) {
+ outfile = FileUtils.newFileUtils().resolveFile( dir, output );
+ }
+ else {
+ outfile = getProject().resolveFile( output );
+ }
+ try {
+ out = new PrintStream( new FileOutputStream( outfile ) );
+ DefaultLogger logger = new DefaultLogger();
+ logger.setMessageOutputLevel( Project.MSG_INFO );
+ logger.setOutputPrintStream( out );
+ logger.setErrorPrintStream( out );
+ newProject.addBuildListener( logger );
+ }
+ catch ( IOException ex ) {
+ log( "Ant: Can't set output to " + output );
+ }
+ }
+
+ Hashtable taskdefs = getProject().getTaskDefinitions();
+ Enumeration et = taskdefs.keys();
+ while ( et.hasMoreElements() ) {
+ String taskName = (String)et.nextElement();
+ if ( taskName.equals( "property" ) ) {
+ // we have already added this taskdef in #init
+ continue;
+ }
+ Class taskClass = (Class)taskdefs.get( taskName );
+ newProject.addTaskDefinition( taskName, taskClass );
+ }
+
+ Hashtable typedefs = getProject().getDataTypeDefinitions();
+ Enumeration e = typedefs.keys();
+ while ( e.hasMoreElements() ) {
+ String typeName = (String)e.nextElement();
+ Class typeClass = (Class)typedefs.get( typeName );
+ newProject.addDataTypeDefinition( typeName, typeClass );
+ }
+
+ // set user-defined properties
+ getProject().copyUserProperties( newProject );
+
+ if ( !inheritAll ) {
+ // set Java built-in properties separately,
+ // b/c we won't inherit them.
+ newProject.setSystemProperties();
+
+ }
+ else {
+ // set all properties from calling project
+
+ Hashtable props = getProject().getProperties();
+ e = props.keys();
+ while ( e.hasMoreElements() ) {
+ String arg = e.nextElement().toString();
+ if ( "basedir".equals( arg ) || "ant.file".equals( arg ) ) {
+ // basedir and ant.file get special treatment in execute()
+ continue;
+ }
+
+ String value = props.get( arg ).toString();
+ // don't re-set user properties, avoid the warning message
+ if ( newProject.getProperty( arg ) == null ) {
+ // no user property
+ newProject.setNewProperty( arg, value );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Pass output sent to System.out to the new project.
+ *
+ * @param line Description of the Parameter
+ * @since Ant 1.5
+ */
+ protected void handleOutput( String line ) {
+ if ( newProject != null ) {
+ newProject.demuxOutput( line, false );
+ }
+ else {
+ super.handleOutput( line );
+ }
+ }
+
+
+ /**
+ * Pass output sent to System.err to the new project.
+ *
+ * @param line Description of the Parameter
+ * @since Ant 1.5
+ */
+ protected void handleErrorOutput( String line ) {
+ if ( newProject != null ) {
+ newProject.demuxOutput( line, true );
+ }
+ else {
+ super.handleErrorOutput( line );
+ }
+ }
+
+
+ /**
+ * Do the execution.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ public void execute() throws BuildException {
+ File savedDir = dir;
+ String savedAntFile = antFile;
+ String savedTarget = target;
+ try {
+ if ( newProject == null ) {
+ reinit();
+ }
+
+ if ( ( dir == null ) && ( inheritAll ) ) {
+ dir = getProject().getBaseDir();
+ }
+
+ initializeProject();
+
+ if ( dir != null ) {
+ newProject.setBaseDir( dir );
+ if ( savedDir != null ) { // has been set explicitly
+ newProject.setInheritedProperty( "basedir",
+ dir.getAbsolutePath() );
+ }
+ }
+ else {
+ dir = getProject().getBaseDir();
+ }
+
+ overrideProperties();
+
+ if ( antFile == null ) {
+ antFile = "build.xml";
+ }
+
+ File file = FileUtils.newFileUtils().resolveFile( dir, antFile );
+ antFile = file.getAbsolutePath();
+
+ log( "calling target " + ( target != null ? target : "[default]" )
+ + " in build file " + antFile.toString(),
+ Project.MSG_VERBOSE );
+ newProject.setUserProperty( "ant.file", antFile );
+ ProjectHelper.configureProject( newProject, new File( antFile ) );
+
+ if ( target == null ) {
+ target = newProject.getDefaultTarget();
+ }
+
+ addReferences();
+
+ // Are we trying to call the target in which we are defined?
+ if ( newProject.getBaseDir().equals( getProject().getBaseDir() ) &&
+ newProject.getProperty( "ant.file" ).equals( getProject().getProperty( "ant.file" ) ) &&
+ getOwningTarget() != null &&
+ target.equals( this.getOwningTarget().getName() ) ) {
+
+ throw new BuildException( "ant task calling its own parent "
+ + "target" );
+ }
+
+ newProject.executeTarget( target );
+
+ // copy back the props if possible
+ if ( returnName != null ) {
+ StringTokenizer st = new StringTokenizer( returnName, "," );
+ while ( st.hasMoreTokens() ) {
+ String name = st.nextToken().trim();
+ String value = newProject.getUserProperty( name );
+ if ( value != null ) {
+ getProject().setUserProperty( name, value );
+ }
+ else {
+ value = newProject.getProperty( name );
+ if ( value != null ) {
+ getProject().setProperty( name, value );
+ }
+ }
+ }
+ }
+ }
+ finally {
+ // help the gc
+ newProject = null;
+ if ( output != null && out != null ) {
+ try {
+ out.close();
+ }
+ catch ( final Exception e ) {
+ //ignore
+ }
+ }
+ dir = savedDir;
+ antFile = savedAntFile;
+ target = savedTarget;
+ }
+ }
+
+
+ /**
+ * Override the properties in the new project with the one explicitly defined
+ * as nested elements here.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ private void overrideProperties() throws BuildException {
+ Enumeration e = properties.elements();
+ while ( e.hasMoreElements() ) {
+ Property p = (Property)e.nextElement();
+ p.setProject( newProject );
+ p.execute();
+ }
+ getProject().copyInheritedProperties( newProject );
+ }
+
+
+ /**
+ * Add the references explicitly defined as nested elements to the new
+ * project. Also copy over all references that don't override existing
+ * references in the new project if inheritrefs has been requested.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ private void addReferences() throws BuildException {
+ Hashtable thisReferences = (Hashtable)getProject().getReferences().clone();
+ Hashtable newReferences = newProject.getReferences();
+ Enumeration e;
+ if ( references.size() > 0 ) {
+ for ( e = references.elements(); e.hasMoreElements(); ) {
+ Reference ref = (Reference)e.nextElement();
+ String refid = ref.getRefId();
+ if ( refid == null ) {
+ throw new BuildException( "the refid attribute is required"
+ + " for reference elements" );
+ }
+ if ( !thisReferences.containsKey( refid ) ) {
+ log( "Parent project doesn't contain any reference '"
+ + refid + "'",
+ Project.MSG_WARN );
+ continue;
+ }
+
+ thisReferences.remove( refid );
+ String toRefid = ref.getToRefid();
+ if ( toRefid == null ) {
+ toRefid = refid;
+ }
+ copyReference( refid, toRefid );
+ }
+ }
+
+ // Now add all references that are not defined in the
+ // subproject, if inheritRefs is true
+ if ( inheritRefs ) {
+ for ( e = thisReferences.keys(); e.hasMoreElements(); ) {
+ String key = (String)e.nextElement();
+ if ( newReferences.containsKey( key ) ) {
+ continue;
+ }
+ copyReference( key, key );
+ }
+ }
+ }
+
+
+ /**
+ * Try to clone and reconfigure the object referenced by oldkey in the parent
+ * project and add it to the new project with the key newkey. <p>
+ *
+ * If we cannot clone it, copy the referenced object itself and keep our
+ * fingers crossed.</p>
+ *
+ * @param oldKey Description of the Parameter
+ * @param newKey Description of the Parameter
+ */
+ private void copyReference( String oldKey, String newKey ) {
+ Object orig = getProject().getReference( oldKey );
+ Class c = orig.getClass();
+ Object copy = orig;
+ try {
+ Method cloneM = c.getMethod( "clone", new Class[0] );
+ if ( cloneM != null ) {
+ copy = cloneM.invoke( orig, new Object[0] );
+ }
+ }
+ catch ( Exception e ) {
+ // not Clonable
+ }
+
+ if ( copy instanceof ProjectComponent ) {
+ ( (ProjectComponent)copy ).setProject( newProject );
+ }
+ else {
+ try {
+ Method setProjectM =
+ c.getMethod( "setProject", new Class[]{Project.class} );
+ if ( setProjectM != null ) {
+ setProjectM.invoke( copy, new Object[]{newProject} );
+ }
+ }
+ catch ( NoSuchMethodException e ) {
+ // ignore this if the class being referenced does not have
+ // a set project method.
+ }
+ catch ( Exception e2 ) {
+ String msg = "Error setting new project instance for "
+ + "reference with id " + oldKey;
+ throw new BuildException( msg, e2, getLocation() );
+ }
+ }
+ newProject.addReference( newKey, copy );
+ }
+
+
+ /**
+ * The directory to use as a base directory for the new Ant project. Defaults
+ * to the current project's basedir, unless inheritall has been set to false,
+ * in which case it doesn't have a default value. This will override the
+ * basedir setting of the called project.
+ *
+ * @param d The new dir value
+ */
+ public void setDir( File d ) {
+ this.dir = d;
+ }
+
+
+ /**
+ * The build file to use. Defaults to "build.xml". This file is expected to
+ * be a filename relative to the dir attribute given.
+ *
+ * @param s The new antfile value
+ */
+ 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;
+ }
+
+
+ /**
+ * The target of the new Ant project to execute. Defaults to the new
+ * project's default target.
+ *
+ * @param s The new target value
+ */
+ public void setTarget( String s ) {
+ this.target = s;
+ }
+
+
+ /**
+ * Filename to write the output to. This is relative to the value of the dir
+ * attribute if it has been set or to the base directory of the current
+ * project otherwise.
+ *
+ * @param s The new output value
+ */
+ public void setOutput( String s ) {
+ this.output = s;
+ }
+
+
+ /**
+ * Property to pass to the new project. The property is passed as a 'user
+ * property'
+ *
+ * @return Description of the Return Value
+ */
+ public Property createProperty() {
+ if ( newProject == null ) {
+ reinit();
+ }
+ /*
+ * Property p = new Property( true, getProject() );
+ */
+ Property p = new Property();
+ p.setProject( newProject );
+ p.setTaskName( "property" );
+ properties.addElement( p );
+ return p;
+ }
+
+
+ /**
+ * Set the property or properties that are set in the new project to be
+ * transfered back to the original project. As with all properties, if the
+ * property already exists in the original project, it will not be overridden
+ * by a different value from the new project.
+ *
+ * @param r the name of a property in the new project to set in the original
+ * project. This may be a comma separate list of properties.
+ */
+ public void setReturn( String r ) {
+ returnName = r;
+ }
+
+
+ /**
+ * Reference element identifying a data type to carry over to the new
+ * project.
+ *
+ * @param r The feature to be added to the Reference attribute
+ */
+ public void addReference( Reference r ) {
+ references.addElement( r );
+ }
+
+
+ /**
+ * Helper class that implements the nested &lt;reference&gt; element of
+ * &lt;ant&gt; and &lt;antcall&gt;.
+ *
+ * @author danson
+ */
+ public static class Reference
+ extends org.apache.tools.ant.types.Reference {
+
+ /** Creates a reference to be configured by Ant */
+ public Reference() {
+ super();
+ }
+
+
+ private String targetid = null;
+
+
+ /**
+ * Set the id that this reference to be stored under in the new project.
+ *
+ * @param targetid the id under which this reference will be passed to
+ * the new project
+ */
+ public void setToRefid( String targetid ) {
+ this.targetid = targetid;
+ }
+
+
+ /**
+ * Get the id under which this reference will be stored in the new project
+ *
+ * @return the id of the reference in the new project.
+ */
+ public String getToRefid() {
+ return targetid;
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/logic/Assert.java b/src/java/net/sf/antcontrib/logic/Assert.java
new file mode 100644
index 0000000..38ac6e8
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/Assert.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.taskdefs.Exit;
+import org.apache.tools.ant.taskdefs.Sequential;
+import org.apache.tools.ant.taskdefs.condition.Condition;
+import org.apache.tools.ant.taskdefs.condition.ConditionBase;
+
+
+/**
+ *
+ */
+public class Assert
+ extends ConditionBase
+ implements TaskContainer {
+
+ private List tasks = new ArrayList();
+ private String message;
+ private boolean failOnError;
+
+
+ public void setFailOnError(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public void addTask(Task task) {
+ tasks.add(task);
+ }
+
+ public void execute() {
+ if (countConditions() == 0) {
+ throw new BuildException("There is no condition specified.");
+ }
+ else if (countConditions() > 1) {
+ throw new BuildException("There must be exactly one condition specified.");
+ }
+
+ Sequential sequential = (Sequential) getProject().createTask("sequential");
+ Condition c = (Condition) getConditions().nextElement();
+ if (! c.eval()) {
+ if (failOnError) {
+ Exit fail = (Exit) getProject().createTask("fail");
+ fail.setMessage(message);
+ sequential.addTask(fail);
+ }
+ }
+ else {
+ Iterator it = tasks.iterator();
+ while (it.hasNext()) {
+ sequential.addTask((Task)it.next());
+ }
+ }
+ }
+
+
+}
diff --git a/src/java/net/sf/antcontrib/logic/ForEach.java b/src/java/net/sf/antcontrib/logic/ForEach.java
new file mode 100644
index 0000000..ad822f0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/ForEach.java
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.taskdefs.Ant;
+import org.apache.tools.ant.taskdefs.CallTarget;
+import org.apache.tools.ant.taskdefs.Property;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Mapper;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileNameMapper;
+
+import net.sf.antcontrib.util.ThreadPool;
+import net.sf.antcontrib.util.ThreadPoolThread;
+
+/***
+ * Task definition for the foreach task. The foreach task iterates
+ * over a list, a list of filesets, or both.
+ *
+ * <pre>
+ *
+ * Usage:
+ *
+ * Task declaration in the project:
+ * <code>
+ * &lt;taskdef name="foreach" classname="net.sf.antcontrib.logic.ForEach" /&gt;
+ * </code>
+ *
+ * Call Syntax:
+ * <code>
+ * &lt;foreach list="values" target="targ" param="name"
+ * [parallel="true|false"]
+ * [delimiter="delim"] /&gt;
+ * </code>
+ *
+ * Attributes:
+ * list --> The list of values to process, with the delimiter character,
+ * indicated by the "delim" attribute, separating each value
+ * target --> The target to call for each token, passing the token as the
+ * parameter with the name indicated by the "param" attribute
+ * param --> The name of the parameter to pass the tokens in as to the
+ * target
+ * delimiter --> The delimiter string that separates the values in the "list"
+ * parameter. The default is ","
+ * parallel --> Should all targets execute in parallel. The default is false.
+ * trim --> Should we trim the list item before calling the target?
+ *
+ * </pre>
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ */
+public class ForEach extends Task
+{
+ private String list;
+ private String param;
+ private String delimiter;
+ private String target;
+ private boolean inheritAll;
+ private boolean inheritRefs;
+ private Vector params;
+ private Vector references;
+ private Path currPath;
+ private boolean parallel;
+ private boolean trim;
+ private int maxThreads;
+ private Mapper mapper;
+
+ /***
+ * Default Constructor
+ */
+ public ForEach()
+ {
+ super();
+ this.list = null;
+ this.param = null;
+ this.delimiter = ",";
+ this.target = null;
+ this.inheritAll = false;
+ this.inheritRefs = false;
+ this.params = new Vector();
+ this.references = new Vector();
+ this.parallel = false;
+ this.maxThreads = 5;
+ }
+
+ private void executeParallel(Vector tasks)
+ {
+ ThreadPool pool = new ThreadPool(maxThreads);
+ Enumeration e = tasks.elements();
+ Runnable r = null;
+ Vector threads = new Vector();
+
+ // start each task in it's own thread, using the
+ // pool to ensure that we don't exceed the maximum
+ // amount of threads
+ while (e.hasMoreElements())
+ {
+ // Create the Runnable object
+ final Task task = (Task)e.nextElement();
+ r = new Runnable()
+ {
+ public void run()
+ {
+ task.execute();
+ }
+ };
+
+ // Get a thread, and start the task.
+ // If there is no thread available, this will
+ // block until one becomes available
+ try
+ {
+ ThreadPoolThread tpt = pool.borrowThread();
+ tpt.setRunnable(r);
+ tpt.start();
+ threads.addElement(tpt);
+ }
+ catch (Exception ex)
+ {
+ throw new BuildException(ex);
+ }
+
+ }
+
+ // Wait for all threads to finish before we
+ // are allowed to return.
+ Enumeration te = threads.elements();
+ Thread t= null;
+ while (te.hasMoreElements())
+ {
+ t = (Thread)te.nextElement();
+ if (t.isAlive())
+ {
+ try
+ {
+ t.join();
+ }
+ catch (InterruptedException ex)
+ {
+ throw new BuildException(ex);
+ }
+ }
+ }
+ }
+
+ private void executeSequential(Vector tasks)
+ {
+ TaskContainer tc = (TaskContainer) getProject().createTask("sequential");
+ Enumeration e = tasks.elements();
+ Task t = null;
+ while (e.hasMoreElements())
+ {
+ t = (Task)e.nextElement();
+ tc.addTask(t);
+ }
+
+ ((Task)tc).execute();
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ if (list == null && currPath == null) {
+ throw new BuildException("You must have a list or path to iterate through");
+ }
+ if (param == null)
+ throw new BuildException("You must supply a property name to set on each iteration in param");
+ if (target == null)
+ throw new BuildException("You must supply a target to perform");
+
+ Vector values = new Vector();
+
+ // Take Care of the list attribute
+ if (list != null)
+ {
+ StringTokenizer st = new StringTokenizer(list, delimiter);
+
+ while (st.hasMoreTokens())
+ {
+ String tok = st.nextToken();
+ if (trim) tok = tok.trim();
+ values.addElement(tok);
+ }
+ }
+
+ String[] pathElements = new String[0];
+ if (currPath != null) {
+ pathElements = currPath.list();
+ }
+
+ for (int i=0;i<pathElements.length;i++)
+ {
+ if (mapper != null)
+ {
+ FileNameMapper m = mapper.getImplementation();
+ String mapped[] = m.mapFileName(pathElements[i]);
+ for (int j=0;j<mapped.length;j++)
+ values.addElement(mapped[j]);
+ }
+ else
+ {
+ values.addElement(new File(pathElements[i]));
+ }
+ }
+
+ Vector tasks = new Vector();
+
+ int sz = values.size();
+ CallTarget ct = null;
+ Object val = null;
+ Property p = null;
+
+ for (int i = 0; i < sz; i++) {
+ val = values.elementAt(i);
+ ct = createCallTarget();
+ p = ct.createParam();
+ p.setName(param);
+
+ if (val instanceof File)
+ p.setLocation((File)val);
+ else
+ p.setValue((String)val);
+
+ tasks.addElement(ct);
+ }
+
+ if (parallel && maxThreads > 1)
+ {
+ executeParallel(tasks);
+ }
+ else
+ {
+ executeSequential(tasks);
+ }
+ }
+
+ public void setTrim(boolean trim)
+ {
+ this.trim = trim;
+ }
+
+ public void setList(String list)
+ {
+ this.list = list;
+ }
+
+ public void setDelimiter(String delimiter)
+ {
+ this.delimiter = delimiter;
+ }
+
+ public void setParam(String param)
+ {
+ this.param = param;
+ }
+
+ public void setTarget(String target)
+ {
+ this.target = target;
+ }
+
+ public void setParallel(boolean parallel)
+ {
+ this.parallel = parallel;
+ }
+
+ /**
+ * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritall</code>
+ * attribute.
+ */
+ public void setInheritall(boolean b) {
+ this.inheritAll = b;
+ }
+
+ /**
+ * Corresponds to <code>&lt;antcall&gt;</code>'s <code>inheritrefs</code>
+ * attribute.
+ */
+ public void setInheritrefs(boolean b) {
+ this.inheritRefs = b;
+ }
+
+
+ /***
+ * Set the maximum amount of threads we're going to allow
+ * at once to execute
+ * @param maxThreads
+ */
+ public void setMaxThreads(int maxThreads)
+ {
+ this.maxThreads = maxThreads;
+ }
+
+
+ /**
+ * Corresponds to <code>&lt;antcall&gt;</code>'s nested
+ * <code>&lt;param&gt;</code> element.
+ */
+ public void addParam(Property p) {
+ params.addElement(p);
+ }
+
+ /**
+ * Corresponds to <code>&lt;antcall&gt;</code>'s nested
+ * <code>&lt;reference&gt;</code> element.
+ */
+ public void addReference(Ant.Reference r) {
+ references.addElement(r);
+ }
+
+ /**
+ * @deprecated Use createPath instead.
+ */
+ public void addFileset(FileSet set)
+ {
+ log("The nested fileset element is deprectated, use a nested path "
+ + "instead",
+ Project.MSG_WARN);
+ createPath().addFileset(set);
+ }
+
+ public Path createPath() {
+ if (currPath == null) {
+ currPath = new Path(getProject());
+ }
+ return currPath;
+ }
+
+ public Mapper createMapper()
+ {
+ mapper = new Mapper(getProject());
+ return mapper;
+ }
+
+ private CallTarget createCallTarget() {
+ CallTarget ct = (CallTarget) getProject().createTask("antcall");
+ ct.setOwningTarget(getOwningTarget());
+ ct.init();
+ ct.setTarget(target);
+ ct.setInheritAll(inheritAll);
+ ct.setInheritRefs(inheritRefs);
+ Enumeration e = params.elements();
+ while (e.hasMoreElements()) {
+ Property param = (Property) e.nextElement();
+ Property toSet = ct.createParam();
+ toSet.setName(param.getName());
+ if (param.getValue() != null) {
+ toSet.setValue(param.getValue());
+ }
+ if (param.getFile() != null) {
+ toSet.setFile(param.getFile());
+ }
+ if (param.getResource() != null) {
+ toSet.setResource(param.getResource());
+ }
+ if (param.getPrefix() != null) {
+ toSet.setPrefix(param.getPrefix());
+ }
+ if (param.getRefid() != null) {
+ toSet.setRefid(param.getRefid());
+ }
+ if (param.getEnvironment() != null) {
+ toSet.setEnvironment(param.getEnvironment());
+ }
+ if (param.getClasspath() != null) {
+ toSet.setClasspath(param.getClasspath());
+ }
+ }
+
+ e = references.elements();
+ while (e.hasMoreElements()) {
+ ct.addReference((Ant.Reference) e.nextElement());
+ }
+
+ return ct;
+ }
+
+ protected void handleOutput(String line)
+ {
+ try {
+ super.handleOutput(line);
+ }
+ // This is needed so we can run with 1.5 and 1.5.1
+ catch (IllegalAccessError e) {
+ super.handleOutput(line);
+ }
+ }
+
+ protected void handleErrorOutput(String line)
+ {
+ try {
+ super.handleErrorOutput(line);
+ }
+ // This is needed so we can run with 1.5 and 1.5.1
+ catch (IllegalAccessError e) {
+ super.handleErrorOutput(line);
+ }
+ }
+
+}
+
+
diff --git a/src/java/net/sf/antcontrib/logic/ForTask.java b/src/java/net/sf/antcontrib/logic/ForTask.java
new file mode 100644
index 0000000..516773b
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/ForTask.java
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2003-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.MacroDef;
+import org.apache.tools.ant.taskdefs.MacroInstance;
+import org.apache.tools.ant.taskdefs.Parallel;
+import org.apache.tools.ant.types.DirSet;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+
+/***
+ * Task definition for the for task. This is based on
+ * the foreach task but takes a sequential element
+ * instead of a target and only works for ant >= 1.6Beta3
+ * @author Peter Reilly
+ */
+public class ForTask extends Task {
+
+ private String list;
+ private String param;
+ private String delimiter = ",";
+ private Path currPath;
+ private boolean trim;
+ private boolean keepgoing = false;
+ private MacroDef macroDef;
+ private List hasIterators = new ArrayList();
+ private boolean parallel = false;
+ private Integer threadCount;
+ private Parallel parallelTasks;
+
+ /**
+ * Creates a new <code>For</code> instance.
+ * This checks if the ant version is correct to run this task.
+ */
+ public ForTask() {
+ }
+
+ /**
+ * Attribute whether to execute the loop in parallel or in sequence.
+ * @param parallel if true execute the tasks in parallel. Default is false.
+ */
+ public void setParallel(boolean parallel) {
+ this.parallel = parallel;
+ }
+
+ /***
+ * Set the maximum amount of threads we're going to allow
+ * to execute in parallel
+ * @param threadCount the number of threads to use
+ */
+ public void setThreadCount(int threadCount) {
+ if (threadCount < 1) {
+ throw new BuildException("Illegal value for threadCount " + threadCount
+ + " it should be > 0");
+ }
+ this.threadCount = new Integer(threadCount);
+ }
+
+ /**
+ * Set the trim attribute.
+ *
+ * @param trim if true, trim the value for each iterator.
+ */
+ public void setTrim(boolean trim) {
+ this.trim = trim;
+ }
+
+ /**
+ * Set the keepgoing attribute, indicating whether we
+ * should stop on errors or continue heedlessly onward.
+ *
+ * @param keepgoing a boolean, if <code>true</code> then we act in
+ * the keepgoing manner described.
+ */
+ public void setKeepgoing(boolean keepgoing) {
+ this.keepgoing = keepgoing;
+ }
+
+ /**
+ * Set the list attribute.
+ *
+ * @param list a list of delimiter separated tokens.
+ */
+ public void setList(String list) {
+ this.list = list;
+ }
+
+ /**
+ * Set the delimiter attribute.
+ *
+ * @param delimiter the delimiter used to separate the tokens in
+ * the list attribute. The default is ",".
+ */
+ public void setDelimiter(String delimiter) {
+ this.delimiter = delimiter;
+ }
+
+ /**
+ * Set the param attribute.
+ * This is the name of the macrodef attribute that
+ * gets set for each iterator of the sequential element.
+ *
+ * @param param the name of the macrodef attribute.
+ */
+ public void setParam(String param) {
+ this.param = param;
+ }
+
+ private Path getOrCreatePath() {
+ if (currPath == null) {
+ currPath = new Path(getProject());
+ }
+ return currPath;
+ }
+
+ /**
+ * This is a path that can be used instread of the list
+ * attribute to interate over. If this is set, each
+ * path element in the path is used for an interator of the
+ * sequential element.
+ *
+ * @param path the path to be set by the ant script.
+ */
+ public void addConfigured(Path path) {
+ getOrCreatePath().append(path);
+ }
+
+ /**
+ * This is a path that can be used instread of the list
+ * attribute to interate over. If this is set, each
+ * path element in the path is used for an interator of the
+ * sequential element.
+ *
+ * @param path the path to be set by the ant script.
+ */
+ public void addConfiguredPath(Path path) {
+ addConfigured(path);
+ }
+
+ /**
+ * @return a MacroDef#NestedSequential object to be configured
+ */
+ public Object createSequential() {
+ macroDef = new MacroDef();
+ macroDef.setProject(getProject());
+ return macroDef.createSequential();
+ }
+
+ /**
+ * Run the for task.
+ * This checks the attributes and nested elements, and
+ * if there are ok, it calls doTheTasks()
+ * which constructes a macrodef task and a
+ * for each interation a macrodef instance.
+ */
+ public void execute() {
+ if (parallel) {
+ parallelTasks = (Parallel) getProject().createTask("parallel");
+ if (threadCount != null) {
+ parallelTasks.setThreadCount(threadCount.intValue());
+ }
+ }
+ if (list == null && currPath == null && hasIterators.size() == 0) {
+ throw new BuildException(
+ "You must have a list or path to iterate through");
+ }
+ if (param == null) {
+ throw new BuildException(
+ "You must supply a property name to set on"
+ + " each iteration in param");
+ }
+ if (macroDef == null) {
+ throw new BuildException(
+ "You must supply an embedded sequential "
+ + "to perform");
+ }
+ doTheTasks();
+ if (parallel) {
+ parallelTasks.perform();
+ }
+ }
+
+
+ private void doSequentialIteration(String val) {
+ MacroInstance instance = new MacroInstance();
+ instance.setProject(getProject());
+ instance.setOwningTarget(getOwningTarget());
+ instance.setMacroDef(macroDef);
+ instance.setDynamicAttribute(param.toLowerCase(),
+ val);
+ if (!parallel) {
+ instance.execute();
+ } else {
+ parallelTasks.addTask(instance);
+ }
+ }
+
+ private void doTheTasks() {
+ int errorCount = 0;
+ int taskCount = 0;
+
+ // Create a macro attribute
+ MacroDef.Attribute attribute = new MacroDef.Attribute();
+ attribute.setName(param);
+ macroDef.addConfiguredAttribute(attribute);
+ // Take Care of the list attribute
+ if (list != null) {
+ StringTokenizer st = new StringTokenizer(list, delimiter);
+
+ while (st.hasMoreTokens()) {
+ String tok = st.nextToken();
+ if (trim) {
+ tok = tok.trim();
+ }
+ try {
+ taskCount++;
+ doSequentialIteration(tok);
+ } catch (BuildException bx) {
+ if (keepgoing) {
+ log(tok + ": " + bx.getMessage(), Project.MSG_ERR);
+ errorCount++;
+ } else {
+ throw bx;
+ }
+ }
+ }
+ }
+ if (keepgoing && (errorCount != 0)) {
+ throw new BuildException(
+ "Keepgoing execution: " + errorCount
+ + " of " + taskCount + " iterations failed.");
+ }
+
+ // Take Care of the path element
+ String[] pathElements = new String[0];
+ if (currPath != null) {
+ pathElements = currPath.list();
+ }
+ for (int i = 0; i < pathElements.length; i++) {
+ File nextFile = new File(pathElements[i]);
+ try {
+ taskCount++;
+ doSequentialIteration(nextFile.getAbsolutePath());
+ } catch (BuildException bx) {
+ if (keepgoing) {
+ log(nextFile + ": " + bx.getMessage(), Project.MSG_ERR);
+ errorCount++;
+ } else {
+ throw bx;
+ }
+ }
+ }
+ if (keepgoing && (errorCount != 0)) {
+ throw new BuildException(
+ "Keepgoing execution: " + errorCount
+ + " of " + taskCount + " iterations failed.");
+ }
+
+ // Take care of iterators
+ for (Iterator i = hasIterators.iterator(); i.hasNext();) {
+ Iterator it = ((HasIterator) i.next()).iterator();
+ while (it.hasNext()) {
+ String s = it.next().toString();
+ try {
+ taskCount++;
+ doSequentialIteration(s);
+ } catch (BuildException bx) {
+ if (keepgoing) {
+ log(s + ": " + bx.getMessage(), Project.MSG_ERR);
+ errorCount++;
+ } else {
+ throw bx;
+ }
+ }
+ }
+ }
+ if (keepgoing && (errorCount != 0)) {
+ throw new BuildException(
+ "Keepgoing execution: " + errorCount
+ + " of " + taskCount + " iterations failed.");
+ }
+ }
+
+ /**
+ * Add a Map, iterate over the values
+ *
+ * @param map a Map object - iterate over the values.
+ */
+ public void add(Map map) {
+ hasIterators.add(new MapIterator(map));
+ }
+
+ /**
+ * Add a fileset to be iterated over.
+ *
+ * @param fileset a <code>FileSet</code> value
+ */
+ public void add(FileSet fileset) {
+ getOrCreatePath().addFileset(fileset);
+ }
+
+ /**
+ * Add a fileset to be iterated over.
+ *
+ * @param fileset a <code>FileSet</code> value
+ */
+ public void addFileSet(FileSet fileset) {
+ add(fileset);
+ }
+
+ /**
+ * Add a dirset to be iterated over.
+ *
+ * @param dirset a <code>DirSet</code> value
+ */
+ public void add(DirSet dirset) {
+ getOrCreatePath().addDirset(dirset);
+ }
+
+ /**
+ * Add a dirset to be iterated over.
+ *
+ * @param dirset a <code>DirSet</code> value
+ */
+ public void addDirSet(DirSet dirset) {
+ add(dirset);
+ }
+
+ /**
+ * Add a collection that can be iterated over.
+ *
+ * @param collection a <code>Collection</code> value.
+ */
+ public void add(Collection collection) {
+ hasIterators.add(new ReflectIterator(collection));
+ }
+
+ /**
+ * Add an iterator to be iterated over.
+ *
+ * @param iterator an <code>Iterator</code> value
+ */
+ public void add(Iterator iterator) {
+ hasIterators.add(new IteratorIterator(iterator));
+ }
+
+ /**
+ * Add an object that has an Iterator iterator() method
+ * that can be iterated over.
+ *
+ * @param obj An object that can be iterated over.
+ */
+ public void add(Object obj) {
+ hasIterators.add(new ReflectIterator(obj));
+ }
+
+ /**
+ * Interface for the objects in the iterator collection.
+ */
+ private interface HasIterator {
+ Iterator iterator();
+ }
+
+ private static class IteratorIterator implements HasIterator {
+ private Iterator iterator;
+ public IteratorIterator(Iterator iterator) {
+ this.iterator = iterator;
+ }
+ public Iterator iterator() {
+ return this.iterator;
+ }
+ }
+
+ private static class MapIterator implements HasIterator {
+ private Map map;
+ public MapIterator(Map map) {
+ this.map = map;
+ }
+ public Iterator iterator() {
+ return map.values().iterator();
+ }
+ }
+
+ private static class ReflectIterator implements HasIterator {
+ private Object obj;
+ private Method method;
+ public ReflectIterator(Object obj) {
+ this.obj = obj;
+ try {
+ method = obj.getClass().getMethod(
+ "iterator", new Class[] {});
+ } catch (Throwable t) {
+ throw new BuildException(
+ "Invalid type " + obj.getClass() + " used in For task, it does"
+ + " not have a public iterator method");
+ }
+ }
+
+ public Iterator iterator() {
+ try {
+ return (Iterator) method.invoke(obj, new Object[] {});
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/logic/IfTask.java b/src/java/net/sf/antcontrib/logic/IfTask.java
new file mode 100644
index 0000000..4d538df
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/IfTask.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.antcontrib.logic;
+
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Sequential;
+import org.apache.tools.ant.taskdefs.condition.Condition;
+import org.apache.tools.ant.taskdefs.condition.ConditionBase;
+
+/**
+ * Perform some tasks based on whether a given condition holds true or
+ * not.
+ *
+ * <p>This task is heavily based on the Condition framework that can
+ * be found in Ant 1.4 and later, therefore it cannot be used in
+ * conjunction with versions of Ant prior to 1.4.</p>
+ *
+ * <p>This task doesn't have any attributes, the condition to test is
+ * specified by a nested element - see the documentation of your
+ * <code>&lt;condition&gt;</code> task (see
+ * <a href="http://jakarta.apache.org/ant/manual/CoreTasks/condition.html">the
+ * online documentation</a> for example) for a complete list of nested
+ * elements.</p>
+ *
+ * <p>Just like the <code>&lt;condition&gt;</code> task, only a single
+ * condition can be specified - you combine them using
+ * <code>&lt;and&gt;</code> or <code>&lt;or&gt;</code> conditions.</p>
+ *
+ * <p>In addition to the condition, you can specify three different
+ * child elements, <code>&lt;elseif&gt;</code>, <code>&lt;then&gt;</code> and
+ * <code>&lt;else&gt;</code>. All three subelements are optional.
+ *
+ * Both <code>&lt;then&gt;</code> and <code>&lt;else&gt;</code> must not be
+ * used more than once inside the if task. Both are
+ * containers for Ant tasks, just like Ant's
+ * <code>&lt;parallel&gt;</code> and <code>&lt;sequential&gt;</code>
+ * tasks - in fact they are implemented using the same class as Ant's
+ * <code>&lt;sequential&gt;</code> task.</p>
+ *
+ * The <code>&lt;elseif&gt;</code> behaves exactly like an <code>&lt;if&gt;</code>
+ * except that it cannot contain the <code>&lt;else&gt;</code> element
+ * inside of it. You may specify as may of these as you like, and the
+ * order they are specified is the order they are evaluated in. If the
+ * condition on the <code>&lt;if&gt;</code> is false, then the first
+ * <code>&lt;elseif&gt;</code> who's conditional evaluates to true
+ * will be executed. The <code>&lt;else&gt;</code> will be executed
+ * only if the <code>&lt;if&gt;</code> and all <code>&lt;elseif&gt;</code>
+ * conditions are false.
+ *
+ * <p>Use the following task to define the <code>&lt;if&gt;</code>
+ * task before you use it the first time:</p>
+ *
+ * <pre><code>
+ * &lt;taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" /&gt;
+ * </code></pre>
+ *
+ * <h3>Crude Example</h3>
+ *
+ * <pre><code>
+ * &lt;if&gt;
+ * &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;bar&quot; /&gt;
+ * &lt;then&gt;
+ * &lt;echo message=&quot;The value of property foo is bar&quot; /&gt;
+ * &lt;/then&gt;
+ * &lt;else&gt;
+ * &lt;echo message=&quot;The value of property foo is not bar&quot; /&gt;
+ * &lt;/else&gt;
+ * &lt;/if&gt;
+ * </code>
+ *
+ * <code>
+ * &lt;if&gt;
+ * &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;bar&quot; /&gt;
+ * &lt;then&gt;
+ * &lt;echo message=&quot;The value of property foo is 'bar'&quot; /&gt;
+ * &lt;/then&gt;
+ *
+ * &lt;elseif&gt;
+ * &lt;equals arg1=&quot;${foo}&quot; arg2=&quot;foo&quot; /&gt;
+ * &lt;then&gt;
+ * &lt;echo message=&quot;The value of property foo is 'foo'&quot; /&gt;
+ * &lt;/then&gt;
+ * &lt;/elseif&gt;
+ *
+ * &lt;else&gt;
+ * &lt;echo message=&quot;The value of property foo is not 'foo' or 'bar'&quot; /&gt;
+ * &lt;/else&gt;
+ * &lt;/if&gt;
+ * </code></pre>
+ *
+ * @author <a href="mailto:[email protected]">Stefan Bodewig</a>
+ */
+public class IfTask extends ConditionBase {
+
+ public static final class ElseIf
+ extends ConditionBase
+ {
+ private Sequential thenTasks = null;
+
+ public void addThen(Sequential t)
+ {
+ if (thenTasks != null)
+ {
+ throw new BuildException("You must not nest more than one <then> into <elseif>");
+ }
+ thenTasks = t;
+ }
+
+ public boolean eval()
+ throws BuildException
+ {
+ if (countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <elseif>");
+ }
+ if (countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <elseif>");
+ }
+ Condition c = (Condition) getConditions().nextElement();
+
+ return c.eval();
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ if (thenTasks != null)
+ {
+ thenTasks.execute();
+ }
+ }
+ }
+
+ private Sequential thenTasks = null;
+ private Vector elseIfTasks = new Vector();
+ private Sequential elseTasks = null;
+
+ /***
+ * A nested Else if task
+ */
+ public void addElseIf(ElseIf ei)
+ {
+ elseIfTasks.addElement(ei);
+ }
+
+ /**
+ * A nested &lt;then&gt; element - a container of tasks that will
+ * be run if the condition holds true.
+ *
+ * <p>Not required.</p>
+ */
+ public void addThen(Sequential t) {
+ if (thenTasks != null) {
+ throw new BuildException("You must not nest more than one <then> into <if>");
+ }
+ thenTasks = t;
+ }
+
+ /**
+ * A nested &lt;else&gt; element - a container of tasks that will
+ * be run if the condition doesn't hold true.
+ *
+ * <p>Not required.</p>
+ */
+ public void addElse(Sequential e) {
+ if (elseTasks != null) {
+ throw new BuildException("You must not nest more than one <else> into <if>");
+ }
+ elseTasks = e;
+ }
+
+ public void execute() throws BuildException {
+ if (countConditions() > 1) {
+ throw new BuildException("You must not nest more than one condition into <if>");
+ }
+ if (countConditions() < 1) {
+ throw new BuildException("You must nest a condition into <if>");
+ }
+ Condition c = (Condition) getConditions().nextElement();
+ if (c.eval()) {
+ if (thenTasks != null) {
+ thenTasks.execute();
+ }
+ }
+ else
+ {
+ boolean done = false;
+ int sz = elseIfTasks.size();
+ for (int i=0;i<sz && ! done;i++)
+ {
+
+ ElseIf ei = (ElseIf)(elseIfTasks.elementAt(i));
+ if (ei.eval())
+ {
+ done = true;
+ ei.execute();
+ }
+ }
+
+ if (!done && elseTasks != null)
+ {
+ elseTasks.execute();
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/logic/OutOfDate.java b/src/java/net/sf/antcontrib/logic/OutOfDate.java
new file mode 100644
index 0000000..014a15e
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/OutOfDate.java
@@ -0,0 +1,675 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Parallel;
+import org.apache.tools.ant.taskdefs.Sequential;
+import org.apache.tools.ant.taskdefs.condition.Condition;
+import org.apache.tools.ant.types.Mapper;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileNameMapper;
+import org.apache.tools.ant.util.FileUtils;
+
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+/**
+* Task to help in calling tasks if generated files are older
+* than source files.
+* Sets a given property or runs an internal task.
+*
+* Based on
+* org.apache.org.apache.tools.ant.taskdefs.UpToDate
+*
+* @author peter reilly
+*/
+
+public class OutOfDate extends Task implements Condition {
+
+ /**
+ * Enumerated type for collection attribute
+ *
+ * @see EnumeratedAttribute
+ */
+ public static class CollectionEnum extends EnumeratedAttribute {
+ /** Constants for the enumerations */
+ public static final int
+ SOURCES = 0, TARGETS = 1, ALLSOURCES = 2, ALLTARGETS = 3;
+
+ /**
+ * get the values
+ * @return an array of the allowed values for this attribute.
+ */
+ public String[] getValues() {
+ return new String[] {"sources", "targets", "allsources", "alltargets"};
+ }
+ }
+
+ // attributes and nested elements
+ private Task doTask = null;
+ private String property;
+ private String value = "true";
+ private boolean force = false;
+ private int verbosity = Project.MSG_VERBOSE;
+ private Vector mappers = new Vector();
+ private Path targetpaths = null;
+ private Path sourcepaths = null;
+ private String outputSources = null;
+ private String outputSourcesPath = null;
+ private String outputTargets = null;
+ private String outputTargetsPath = null;
+ private String allTargets = null;
+ private String allTargetsPath = null;
+ private String separator = " ";
+ private DeleteTargets deleteTargets = null;
+ private int collection = CollectionEnum.SOURCES;
+
+ // variables
+ private Hashtable targetSet = new Hashtable();
+ private Hashtable sourceSet = new Hashtable();
+ private Hashtable allTargetSet = new Hashtable();
+ private Hashtable allSourceSet = new Hashtable();
+
+ /**
+ * Set the collection attribute, controls what is
+ * returned by the iterator method.
+ * <dl>
+ * <li>"sources" the sources that are newer than the corresponding targets.</li>
+ * <li>"targets" the targets that are older or not present than the corresponding
+ * sources.</li>
+ * <li>"allsources" all the sources</li>
+ * <li>"alltargets" all the targets</li>
+ * </dl>
+ * @param collection "sources" the changes
+ */
+ public void setCollection(CollectionEnum collection) {
+ this.collection = collection.getIndex();
+ }
+
+ /**
+ * Defines the FileNameMapper to use (nested mapper element).
+ * @return Mappper to be configured
+ */
+ public Mapper createMapper() {
+ MyMapper mapper = new MyMapper(getProject());
+ mappers.addElement(mapper);
+ return mapper;
+ }
+
+ /**
+ * The property to set if any of the target files are outofdate with
+ * regard to any of the source files.
+ *
+ * @param property the name of the property to set if Target is outofdate.
+ */
+ public void setProperty(String property) {
+ this.property = property;
+ }
+
+ /**
+ * The separator to use to separate the files
+ * @param separator separator used in outout properties
+ */
+
+ public void setSeparator(String separator) {
+ this.separator = separator;
+ }
+
+ /**
+ * The value to set the named property to the target files
+ * are outofdate
+ *
+ * @param value the value to set the property
+ */
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ /**
+ * whether to allways be outofdate
+ * @param force true means that outofdate is always set, default
+ * false
+ */
+ public void setForce(boolean force) {
+ this.force = force;
+ }
+
+ /**
+ * whether to have verbose output
+ * @param verbose true means that outofdate outputs debug info
+ */
+ public void setVerbose(boolean verbose) {
+ if (verbose) {
+ this.verbosity = Project.MSG_INFO;
+ } else {
+ this.verbosity = Project.MSG_VERBOSE;
+ }
+ }
+
+ /**
+ * Add to the target files
+ *
+ * @return a path to be configured
+ */
+ public Path createTargetfiles() {
+ if (targetpaths == null) {
+ targetpaths = new Path(getProject());
+ }
+ return targetpaths;
+ }
+
+ /**
+ * Add to the source files
+ *
+ * @return a path to be configured
+ */
+ public Path createSourcefiles() {
+ if (sourcepaths == null) {
+ sourcepaths = new Path(getProject());
+ }
+ return sourcepaths;
+ }
+
+ /**
+ * A property to contain the output source files
+ *
+ * @param outputSources the name of the property
+ */
+ public void setOutputSources(String outputSources) {
+ this.outputSources = outputSources;
+ }
+
+ /**
+ * A property to contain the output target files
+ *
+ * @param outputTargets the name of the property
+ */
+ public void setOutputTargets(String outputTargets) {
+ this.outputTargets = outputTargets;
+ }
+
+ /**
+ * A reference to contain the path of target files that
+ * are outofdate
+ *
+ * @param outputTargetsPath the name of the reference
+ */
+ public void setOutputTargetsPath(String outputTargetsPath) {
+ this.outputTargetsPath = outputTargetsPath;
+ }
+
+ /**
+ * A refernce to contain the path of all the targets
+ *
+ * @param allTargetsPath the name of the reference
+ */
+ public void setAllTargetsPath(String allTargetsPath) {
+ this.allTargetsPath = allTargetsPath;
+ }
+
+ /**
+ * A property to contain all the target filenames
+ *
+ * @param allTargets the name of the property
+ */
+ public void setAllTargets(String allTargets) {
+ this.allTargets = allTargets;
+ }
+
+ /**
+ * A reference to the path containing all the sources files.
+ *
+ * @param outputSourcesPath the name of the reference
+ */
+ public void setOutputSourcesPath(String outputSourcesPath) {
+ this.outputSourcesPath = outputSourcesPath;
+ }
+
+ /**
+ * optional nested delete element
+ * @return an element to be configured
+ */
+ public DeleteTargets createDeleteTargets() {
+ deleteTargets = new DeleteTargets();
+ return deleteTargets;
+ }
+
+ /**
+ * Embedded do parallel
+ * @param doTask the parallel to embed
+ */
+ public void addParallel(Parallel doTask) {
+ if (this.doTask != null) {
+ throw new BuildException(
+ "You must not nest more that one <parallel> or <sequential>"
+ + " into <outofdate>");
+ }
+ this.doTask = doTask;
+ }
+
+ /**
+ * Embedded do sequential.
+ * @param doTask the sequential to embed
+ */
+ public void addSequential(Sequential doTask) {
+ if (this.doTask != null) {
+ throw new BuildException(
+ "You must not nest more that one <parallel> or <sequential>"
+ + " into <outofdate>");
+ }
+ this.doTask = doTask;
+ }
+
+ /**
+ * Evaluate (all) target and source file(s) to
+ * see if the target(s) is/are outoutdate.
+ * @return true if any of the targets are outofdate
+ */
+ public boolean eval() {
+ boolean ret = false;
+ FileUtils fileUtils = FileUtils.newFileUtils();
+ if (sourcepaths == null) {
+ throw new BuildException(
+ "You must specify a <sourcefiles> element.");
+ }
+
+ if (targetpaths == null && mappers.size() == 0) {
+ throw new BuildException(
+ "You must specify a <targetfiles> or <mapper> element.");
+ }
+
+ // Source Paths
+ String[] spaths = sourcepaths.list();
+
+ for (int i = 0; i < spaths.length; i++) {
+ File sourceFile = new File(spaths[i]);
+ if (!sourceFile.exists()) {
+ throw new BuildException(sourceFile.getAbsolutePath()
+ + " not found.");
+ }
+ }
+
+ // Target Paths
+
+ if (targetpaths != null) {
+ String[] paths = targetpaths.list();
+ for (int i = 0; i < paths.length; ++i) {
+ if (targetNeedsGen(paths[i], spaths)) {
+ ret = true;
+ }
+ }
+ }
+
+ // Mapper Paths
+ for (Enumeration e = mappers.elements(); e.hasMoreElements();) {
+ MyMapper mapper = (MyMapper) e.nextElement();
+
+ File relativeDir = mapper.getDir();
+ File baseDir = new File(getProject().getProperty("basedir"));
+ if (relativeDir == null) {
+ relativeDir = baseDir;
+ }
+ String[] rpaths = new String[spaths.length];
+ for (int i = 0; i < spaths.length; ++i) {
+ rpaths[i] = fileUtils.removeLeadingPath(relativeDir, new File(spaths[i]));
+ }
+
+ FileNameMapper fileNameMapper = mapper.getImplementation();
+ for (int i = 0; i < spaths.length; ++i) {
+ String[] mapped = fileNameMapper.mapFileName(rpaths[i]);
+ if (mapped != null) {
+ for (int j = 0; j < mapped.length; ++j) {
+ if (outOfDate(new File(spaths[i]),
+ fileUtils.resolveFile(
+ baseDir, mapped[j]))) {
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (allTargets != null) {
+ this.getProject().setNewProperty(
+ allTargets, setToString(allTargetSet));
+ }
+
+ if (allTargetsPath != null) {
+ this.getProject().addReference(
+ allTargetsPath, setToPath(allTargetSet));
+ }
+
+ if (outputSources != null) {
+ this.getProject().setNewProperty(
+ outputSources, setToString(sourceSet));
+ }
+
+ if (outputTargets != null) {
+ this.getProject().setNewProperty(
+ outputTargets, setToString(targetSet));
+ }
+
+ if (outputSourcesPath != null) {
+ this.getProject().addReference(
+ outputSourcesPath, setToPath(sourceSet));
+ }
+
+ if (outputTargetsPath != null) {
+ this.getProject().addReference(
+ outputTargetsPath, setToPath(targetSet));
+ }
+
+ if (force) {
+ ret = true;
+ }
+
+ if (ret && deleteTargets != null) {
+ deleteTargets.execute();
+ }
+
+ if (ret) {
+ if (property != null) {
+ this.getProject().setNewProperty(property, value);
+ }
+ }
+
+ return ret;
+ }
+
+ private boolean targetNeedsGen(String target, String[] spaths) {
+ boolean ret = false;
+ File targetFile = new File(target);
+ for (int i = 0; i < spaths.length; i++) {
+ if (outOfDate(new File(spaths[i]), targetFile)) {
+ ret = true;
+ }
+ }
+ // Special case : there are no source files, make sure the
+ // targets exist
+ if (spaths.length == 0) {
+ if (outOfDate(null, targetFile)) {
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Call evalute and return an iterator over the result
+ * @return an iterator over the result
+ */
+ public Iterator iterator() {
+ // Perhaps should check the result and return
+ // an empty set if it returns false
+ eval();
+
+ switch (collection) {
+ case CollectionEnum.SOURCES:
+ return sourceSet.values().iterator();
+ case CollectionEnum.TARGETS:
+ return targetSet.values().iterator();
+ case CollectionEnum.ALLSOURCES:
+ return allSourceSet.values().iterator();
+ case CollectionEnum.ALLTARGETS:
+ return allTargetSet.values().iterator();
+ default:
+ return sourceSet.values().iterator();
+ }
+ }
+
+ /**
+ * Sets property to true and/or executes embedded do
+ * if any of the target file(s) do not have a more recent timestamp
+ * than (each of) the source file(s).
+ */
+ public void execute() {
+ if (!eval()) {
+ return;
+ }
+
+ if (doTask != null) {
+ doTask.perform();
+ }
+
+ }
+
+
+ private boolean outOfDate(File sourceFile, File targetFile) {
+ boolean ret = false;
+ if (sourceFile != null) {
+ allSourceSet.put(sourceFile, sourceFile);
+ }
+ allTargetSet.put(targetFile, targetFile);
+ if (!targetFile.exists()) {
+ ret = true;
+ }
+ if ((!ret) && (sourceFile != null)) {
+ ret = sourceFile.lastModified() > targetFile.lastModified();
+ }
+ if (ret) {
+ if ((sourceFile != null && sourceSet.get(sourceFile) == null)
+ || targetSet.get(targetFile) == null) {
+ log("SourceFile " + sourceFile + " outofdate "
+ + "with regard to " + targetFile, verbosity);
+ }
+ if (sourceFile != null) {
+ sourceSet.put(sourceFile, sourceFile);
+ }
+ targetSet.put(targetFile, targetFile);
+ }
+ return ret;
+ }
+
+ private String setToString(Hashtable set) {
+ StringBuffer b = new StringBuffer();
+ for (Enumeration e = set.keys(); e.hasMoreElements();) {
+ File v = (File) e.nextElement();
+ if (b.length() != 0) {
+ b.append(separator);
+ }
+ String s = v.getAbsolutePath();
+ // DOTO: The following needs more work!
+ // Handle paths contains sep
+ if (s.indexOf(separator) != -1) {
+ if (s.indexOf("\"") != -1) {
+ s = "'" + s + "'";
+ } else {
+ s = "\"" + s + "\"";
+ }
+ }
+ b.append(s);
+ }
+ return b.toString();
+ }
+
+ private Path setToPath(Hashtable set) {
+ Path ret = new Path(getProject());
+ for (Enumeration e = set.keys(); e.hasMoreElements();) {
+ File v = (File) e.nextElement();
+ Path.PathElement el = ret.createPathElement();
+ el.setLocation(v);
+ }
+ return ret;
+ }
+
+ /**
+ * nested delete targets
+ */
+ public class DeleteTargets {
+ private boolean all = false;
+ private boolean quiet = false;
+ private boolean failOnError = false;
+
+ private int myLogging = Project.MSG_INFO;
+
+ /**
+ * whether to delete all the targets
+ * or just those that are newer than the
+ * corresponding sources.
+ * @param all true to delete all, default false
+ */
+ public void setAll(boolean all) {
+ this.all = all;
+ }
+
+ /**
+ * @param quiet if true suppress messages on deleting files
+ */
+ public void setQuiet(boolean quiet) {
+ this.quiet = quiet;
+ myLogging = quiet ? Project.MSG_VERBOSE : Project.MSG_INFO;
+ }
+
+ /**
+ * @param failOnError if true halt if there is a failure to delete
+ */
+ public void setFailOnError(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ private void execute() {
+ if (myLogging != Project.MSG_INFO) {
+ myLogging = verbosity;
+ }
+
+ // Quiet overrides failOnError
+ if (quiet) {
+ failOnError = false;
+ }
+
+ Path toBeDeleted = null;
+ if (all) {
+ toBeDeleted = setToPath(allTargetSet);
+ } else {
+ toBeDeleted = setToPath(targetSet);
+ }
+
+ String[] names = toBeDeleted.list();
+ for (int i = 0; i < names.length; ++i) {
+ File file = new File(names[i]);
+ if (!file.exists()) {
+ continue;
+ }
+ if (file.isDirectory()) {
+ removeDir(file);
+ continue;
+ }
+ log("Deleting " + file.getAbsolutePath(), myLogging);
+ if (!file.delete()) {
+ String message =
+ "Unable to delete file " + file.getAbsolutePath();
+ if (failOnError) {
+ throw new BuildException(message);
+ } else {
+ log(message, myLogging);
+ }
+ }
+ }
+ }
+
+ private static final int DELETE_RETRY_SLEEP_MILLIS = 10;
+ /**
+ * Attempt to fix possible race condition when deleting
+ * files on WinXP. If the delete does not work,
+ * wait a little and try again.
+ */
+ private boolean delete(File f) {
+ if (!f.delete()) {
+ try {
+ Thread.sleep(DELETE_RETRY_SLEEP_MILLIS);
+ return f.delete();
+ } catch (InterruptedException ex) {
+ return f.delete();
+ }
+ }
+ return true;
+ }
+
+ private void removeDir(File d) {
+ String[] list = d.list();
+ if (list == null) {
+ list = new String[0];
+ }
+ for (int i = 0; i < list.length; i++) {
+ String s = list[i];
+ File f = new File(d, s);
+ if (f.isDirectory()) {
+ removeDir(f);
+ } else {
+ log("Deleting " + f.getAbsolutePath(), myLogging);
+ if (!f.delete()) {
+ String message = "Unable to delete file "
+ + f.getAbsolutePath();
+ if (failOnError) {
+ throw new BuildException(message);
+ } else {
+ log(message, myLogging);
+ }
+ }
+ }
+ }
+ log("Deleting directory " + d.getAbsolutePath(), myLogging);
+ if (!delete(d)) {
+ String message = "Unable to delete directory "
+ + d.getAbsolutePath();
+ if (failOnError) {
+ throw new BuildException(message);
+ } else {
+ log(message, myLogging);
+ }
+ }
+ }
+ }
+
+ /**
+ * Wrapper for mapper - includes dir
+ */
+ public static class MyMapper extends Mapper {
+ private File dir = null;
+ /**
+ * Creates a new <code>MyMapper</code> instance.
+ *
+ * @param project the current project
+ */
+ public MyMapper(Project project) {
+ super(project);
+ }
+
+ /**
+ * @param dir the directory that the from files are relative to
+ */
+ public void setDir(File dir) {
+ this.dir = dir;
+ }
+
+ /**
+ * @return the directory that the from files are relative to
+ */
+ public File getDir() {
+ return dir;
+ }
+ }
+}
+
+
diff --git a/src/java/net/sf/antcontrib/logic/RunTargetTask.java b/src/java/net/sf/antcontrib/logic/RunTargetTask.java
new file mode 100644
index 0000000..16b87ca
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/RunTargetTask.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+/**
+ * Ant task that runs a target without creating a new project.
+ *
+ * @author Nicola Ken Barozzi [email protected]
+ */
+public class RunTargetTask extends Task {
+
+ private String target = null;
+
+ /**
+ * The target attribute
+ *
+ * @param target the name of a target to execute
+ */
+ public void setTarget(String target) {
+ this.target = target;
+ }
+
+ /**
+ * execute the target
+ *
+ * @exception BuildException if a target is not specified
+ */
+ public void execute() throws BuildException {
+ if (target == null) {
+ throw new BuildException("target property required");
+ }
+
+ getProject().executeTarget(target);
+ }
+}
diff --git a/src/java/net/sf/antcontrib/logic/Switch.java b/src/java/net/sf/antcontrib/logic/Switch.java
new file mode 100644
index 0000000..14f31ec
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/Switch.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Sequential;
+
+/***
+ * Task definition for the ANT task to switch on a particular value.
+ *
+ * <pre>
+ *
+ * Usage:
+ *
+ * Task declaration in the project:
+ * <code>
+ * &lt;taskdef name="switch" classname="net.sf.antcontrib.logic.Switch" /&gt;
+ * </code>
+ *
+ * Task calling syntax:
+ * <code>
+ * &lt;switch value="value" [caseinsensitive="true|false"] &gt;
+ * &lt;case value="val"&gt;
+ * &lt;property name="propname" value="propvalue" /&gt; |
+ * &lt;antcall target="targetname" /&gt; |
+ * any other tasks
+ * &lt;/case&gt;
+ * [
+ * &lt;default&gt;
+ * &lt;property name="propname" value="propvalue" /&gt; |
+ * &lt;antcall target="targetname" /&gt; |
+ * any other tasks
+ * &lt;/default&gt;
+ * ]
+ * &lt;/switch&gt;
+ * </code>
+ *
+ *
+ * Attributes:
+ * value -&gt; The value to switch on
+ * caseinsensitive -&gt; Should we do case insensitive comparisons?
+ * (default is false)
+ *
+ * Subitems:
+ * case --&gt; An individual case to consider, if the value that
+ * is being switched on matches to value attribute of
+ * the case, then the nested tasks will be executed.
+ * default --&gt; The default case for when no match is found.
+ *
+ *
+ * Crude Example:
+ *
+ * <code>
+ * &lt;switch value=&quot;${foo}&quot;&gt;
+ * &lt;case value=&quot;bar&quot;&gt;
+ * &lt;echo message=&quot;The value of property foo is bar&quot; /&gt;
+ * &lt;/case&gt;
+ * &lt;case value=&quot;baz&quot;&gt;
+ * &lt;echo message=&quot;The value of property foo is baz&quot; /&gt;
+ * &lt;/case&gt;
+ * &lt;default&gt;
+ * &lt;echo message=&quot;The value of property foo is not sensible&quot; /&gt;
+ * &lt;/default&gt;
+ * &lt;/switch&gt;
+ * </code>
+ *
+ * </pre>
+ *
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ * @author <a href="mailto:[email protected]">Stefan Bodewig</a>
+ */
+public class Switch extends Task
+{
+ private String value;
+ private Vector cases;
+ private Sequential defaultCase;
+ private boolean caseInsensitive;
+
+ /***
+ * Default Constructor
+ */
+ public Switch()
+ {
+ cases = new Vector();
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ if (value == null)
+ throw new BuildException("Value is missing");
+ if (cases.size() == 0 && defaultCase == null)
+ throw new BuildException("No cases supplied");
+
+ Sequential selectedCase = defaultCase;
+
+ int sz = cases.size();
+ for (int i=0;i<sz;i++)
+ {
+ Case c = (Case)(cases.elementAt(i));
+
+ String cvalue = c.value;
+ if (cvalue == null) {
+ throw new BuildException("Value is required for case.");
+ }
+ String mvalue = value;
+
+ if (caseInsensitive)
+ {
+ cvalue = cvalue.toUpperCase();
+ mvalue = mvalue.toUpperCase();
+ }
+
+ if (cvalue.equals(mvalue) && c != defaultCase)
+ selectedCase = c;
+ }
+
+ if (selectedCase == null) {
+ throw new BuildException("No case matched the value " + value
+ + " and no default has been specified.");
+ }
+ selectedCase.perform();
+ }
+
+ /***
+ * Sets the value being switched on
+ */
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+ public void setCaseInsensitive(boolean c)
+ {
+ caseInsensitive = c;
+ }
+
+ public final class Case extends Sequential
+ {
+ private String value;
+
+ public Case()
+ {
+ super();
+ }
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ super.execute();
+ }
+
+ public boolean equals(Object o)
+ {
+ boolean res = false;
+ Case c = (Case)o;
+ if (c.value.equals(value))
+ res = true;
+ return res;
+ }
+ }
+
+ /***
+ * Creates the &lt;case&gt; tag
+ */
+ public Switch.Case createCase()
+ throws BuildException
+ {
+ Switch.Case res = new Switch.Case();
+ cases.addElement(res);
+ return res;
+ }
+
+ /***
+ * Creates the &lt;default&gt; tag
+ */
+ public void addDefault(Sequential res)
+ throws BuildException
+ {
+ if (defaultCase != null)
+ throw new BuildException("Cannot specify multiple default cases");
+
+ defaultCase = res;
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/logic/Throw.java b/src/java/net/sf/antcontrib/logic/Throw.java
new file mode 100644
index 0000000..552de46
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/Throw.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.Exit;
+import org.apache.tools.ant.types.Reference;
+
+/**
+ * Extension of <code>&lt;fail&gt;</code> that can throw an exception
+ * that is a reference in the project.
+ *
+ * <p>This may be useful inside the <code>&lt;catch&gt;</code> block
+ * of a <code>&lt;trycatch&gt;</code> task if you want to rethrow the
+ * exception just caught.</p>
+ */
+public class Throw extends Exit {
+
+ private Reference ref;
+
+ /**
+ * The reference that points to a BuildException.
+ */
+ public void setRefid(Reference ref) {
+ this.ref = ref;
+ }
+
+ public void execute() throws BuildException {
+ Object reffed = ref != null
+ ? ref.getReferencedObject(getProject())
+ : null;
+ if (reffed != null && reffed instanceof BuildException) {
+ throw (BuildException) reffed;
+ }
+ super.execute();
+ }
+}
diff --git a/src/java/net/sf/antcontrib/logic/TimestampSelector.java b/src/java/net/sf/antcontrib/logic/TimestampSelector.java
new file mode 100644
index 0000000..da4ccd8
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/TimestampSelector.java
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.io.File;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.Reference;
+
+
+/***
+ * Task definition for the foreach task. The foreach task iterates
+ * over a list, a list of filesets, or both.
+ *
+ * <pre>
+ *
+ * Usage:
+ *
+ * Task declaration in the project:
+ * <code>
+ * &lt;taskdef name="latesttimestamp" classname="net.sf.antcontrib.logic.TimestampSelector" /&gt;
+ * </code>
+ *
+ * Call Syntax:
+ * <code>
+ * &lt;timestampselector
+ * [property="prop" | outputsetref="id"]
+ * [count="num"]
+ * [age="eldest|youngest"]
+ * [pathSep=","]
+ * [pathref="ref"] &gt;
+ * &lt;path&gt;
+ * ...
+ * &lt;/path&gt;
+ * &lt;/latesttimestamp&gt;
+ * </code>
+ *
+ * Attributes:
+ * outputsetref --> The reference of the output Path set which will contain the
+ * files with the latest timestamps.
+ * property --> The name of the property to set with file having the latest
+ * timestamp. If you specify the "count" attribute, you will get
+ * the lastest N files. These will be the absolute pathnames
+ * count --> How many of the latest files do you wish to find
+ * pathSep --> What to use as the path separator when using the "property"
+ * attribute, in conjunction with the "count" attribute
+ * pathref --> The reference of the path which is the input set of files.
+ *
+ * </pre>
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ */
+public class TimestampSelector extends Task
+{
+ private static final String AGE_ELDEST = "eldest";
+ private static final String AGE_YOUNGEST = "youngest";
+
+ private String property;
+ private Path path;
+ private String outputSetId;
+ private int count = 1;
+ private char pathSep = ',';
+ private String age = AGE_YOUNGEST;
+
+
+ /***
+ * Default Constructor
+ */
+ public TimestampSelector()
+ {
+ super();
+ }
+
+
+ public void doFileSetExecute(String paths[])
+ throws BuildException
+ {
+
+ }
+
+ // Sorts entire array
+ public void sort(Vector array)
+ {
+ sort(array, 0, array.size() - 1);
+ }
+
+ // Sorts partial array
+ protected void sort(Vector array, int start, int end)
+ {
+ int p;
+ if (end > start)
+ {
+ p = partition(array, start, end);
+ sort(array, start, p-1);
+ sort(array, p+1, end);
+ }
+ }
+
+ protected int compare(File a, File b)
+ {
+ if (age.equalsIgnoreCase(AGE_ELDEST))
+ return new Long(a.lastModified()).compareTo(new Long(b.lastModified()));
+ else
+ return new Long(b.lastModified()).compareTo(new Long(a.lastModified()));
+ }
+
+ protected int partition(Vector array, int start, int end)
+ {
+ int left, right;
+ File partitionElement;
+
+ partitionElement = (File)array.elementAt(end);
+
+ left = start - 1;
+ right = end;
+ for (;;)
+ {
+ while (compare(partitionElement, (File)array.elementAt(++left)) == 1)
+ {
+ if (left == end) break;
+ }
+ while (compare(partitionElement, (File)array.elementAt(--right)) == -1)
+ {
+ if (right == start) break;
+ }
+ if (left >= right) break;
+ swap(array, left, right);
+ }
+ swap(array, left, end);
+
+ return left;
+ }
+
+ protected void swap(Vector array, int i, int j)
+ {
+ Object temp;
+
+ temp = array.elementAt(i);
+ array.setElementAt(array.elementAt(j), i);
+ array.setElementAt(temp, j);
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ if (property == null && outputSetId == null)
+ throw new BuildException("Property or OutputSetId must be specified.");
+ if (path == null)
+ throw new BuildException("A path element or pathref attribute must be specified.");
+
+ // Figure out the list of existing file elements
+ // from the designated path
+ String s[] = path.list();
+ Vector v = new Vector();
+ for (int i=0;i<s.length;i++)
+ {
+ File f = new File(s[i]);
+ if (f.exists())
+ v.addElement(f);
+ }
+
+ // Sort the vector, need to make java 1.1 compliant
+ sort(v);
+
+ // Pull off the first N items
+ Vector v2 = new Vector();
+ int sz = v.size();
+ for (int i=0;i<sz && i<count;i++)
+ v2.add(v.elementAt(i));
+
+
+
+
+ // Build the resulting Path object
+ Path path = new Path(getProject());
+ sz = v2.size();
+ for (int i=0;i<sz;i++)
+ {
+ File f = (File)(v.elementAt(i));
+ Path p = new Path(getProject(), f.getAbsolutePath());
+ path.addExisting(p);
+ }
+
+
+ if (outputSetId != null)
+ {
+ // Add the reference to the project
+ getProject().addReference(outputSetId, path);
+ }
+ else
+ {
+ // Concat the paths, and put them in a property
+ // which is separated list of the files, using the
+ // "pathSep" attribute as the separator
+ String paths[] = path.list();
+ StringBuffer sb = new StringBuffer();
+ for (int i=0;i<paths.length;i++)
+ {
+ if (i != 0) sb.append(pathSep);
+ sb.append(paths[i]);
+ }
+
+ if (paths.length != 0)
+ getProject().setProperty(property, sb.toString());
+ }
+ }
+
+
+ public void setProperty(String property)
+ {
+ if (outputSetId != null)
+ throw new BuildException("Cannot set both Property and OutputSetId.");
+
+ this.property = property;
+ }
+
+ public void setCount(int count)
+ {
+ this.count = count;
+ }
+
+ public void setAge(String age)
+ {
+ if (age.equalsIgnoreCase(AGE_ELDEST) ||
+ age.equalsIgnoreCase(AGE_YOUNGEST))
+ this.age = age;
+ else
+ throw new BuildException("Invalid age: " + age);
+ }
+
+ public void setPathSep(char pathSep)
+ {
+ this.pathSep = pathSep;
+ }
+
+ public void setOutputSetId(String outputSetId)
+ {
+ if (property != null)
+ throw new BuildException("Cannot set both Property and OutputSetId.");
+ this.outputSetId = outputSetId;
+ }
+
+ public void setPathRef(Reference ref)
+ throws BuildException
+ {
+ if (path == null)
+ {
+ path = new Path(getProject());
+ path.setRefid(ref);
+ }
+ else
+ {
+ throw new BuildException("Path element already specified.");
+ }
+ }
+
+
+ public Path createPath()
+ throws BuildException
+ {
+ if (path == null)
+ path = new Path(getProject());
+ else
+ throw new BuildException("Path element already specified.");
+ return path;
+ }
+
+}
+
+
diff --git a/src/java/net/sf/antcontrib/logic/TryCatchTask.java b/src/java/net/sf/antcontrib/logic/TryCatchTask.java
new file mode 100644
index 0000000..4933e7d
--- /dev/null
+++ b/src/java/net/sf/antcontrib/logic/TryCatchTask.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Sequential;
+
+/**
+ * A wrapper that lets you run a set of tasks and optionally run a
+ * different set of tasks if the first set fails and yet another set
+ * after the first one has finished.
+ *
+ * <p>This mirrors Java's try/catch/finally.</p>
+ *
+ * <p>The tasks inside of the required <code>&lt;try&gt;</code>
+ * element will be run. If one of them should throw a {@link
+ * org.apache.tools.ant.BuildException BuildException} several things
+ * can happen:</p>
+ *
+ * <ul>
+ * <li>If there is no <code>&lt;catch&gt;</code> block, the
+ * exception will be passed through to Ant.</li>
+ *
+ * <li>If the property attribute has been set, a property of the
+ * given name will be set to the message of the exception.</li>
+ *
+ * <li>If the reference attribute has been set, a reference of the
+ * given id will be created and point to the exception object.</li>
+ *
+ * <li>If there is a <code>&lt;catch&gt;</code> block, the tasks
+ * nested into it will be run.</li>
+ * </ul>
+ *
+ * <p>If a <code>&lt;finally&gt;</code> block is present, the task
+ * nested into it will be run, no matter whether the first tasks have
+ * thrown an exception or not.</p>
+ *
+ * <p><strong>Attributes:</strong></p>
+ *
+ * <table>
+ * <tr>
+ * <td>Name</td>
+ * <td>Description</td>
+ * <td>Required</td>
+ * </tr>
+ * <tr>
+ * <td>property</td>
+ * <td>Name of a property that will receive the message of the
+ * exception that has been caught (if any)</td>
+ * <td>No</td>
+ * </tr>
+ * <tr>
+ * <td>reference</td>
+ * <td>Id of a reference that will point to the exception object
+ * that has been caught (if any)</td>
+ * <td>No</td>
+ * </tr>
+ * </table>
+ *
+ * <p>Use the following task to define the <code>&lt;trycatch&gt;</code>
+ * task before you use it the first time:</p>
+ *
+ * <pre><code>
+ * &lt;taskdef name="trycatch"
+ * classname="net.sf.antcontrib.logic.TryCatchTask" /&gt;
+ * </code></pre>
+ *
+ * <h3>Crude Example</h3>
+ *
+ * <pre><code>
+ * &lt;trycatch property=&quot;foo&quot; reference=&quot;bar&quot;&gt;
+ * &lt;try&gt;
+ * &lt;fail&gt;Tada!&lt;/fail&gt;
+ * &lt;/try&gt;
+ *
+ * &lt;catch&gt;
+ * &lt;echo&gt;In &amp;lt;catch&amp;gt;.&lt;/echo&gt;
+ * &lt;/catch&gt;
+ *
+ * &lt;finally&gt;
+ * &lt;echo&gt;In &amp;lt;finally&amp;gt;.&lt;/echo&gt;
+ * &lt;/finally&gt;
+ * &lt;/trycatch&gt;
+ *
+ * &lt;echo&gt;As property: ${foo}&lt;/echo&gt;
+ * &lt;property name=&quot;baz&quot; refid=&quot;bar&quot; /&gt;
+ * &lt;echo&gt;From reference: ${baz}&lt;/echo&gt;
+ * </code></pre>
+ *
+ * <p>results in</p>
+ *
+ * <pre><code>
+ * [trycatch] Caught exception: Tada!
+ * [echo] In &lt;catch&gt;.
+ * [echo] In &lt;finally&gt;.
+ * [echo] As property: Tada!
+ * [echo] From reference: Tada!
+ * </code></pre>
+ *
+ * @author <a href="mailto:[email protected]">Stefan Bodewig</a>
+ * @author <a href="mailto:[email protected]">Dan Ritchey</a>
+ */
+public class TryCatchTask extends Task {
+
+ public static final class CatchBlock extends Sequential {
+ private String throwable = BuildException.class.getName();
+
+ public CatchBlock() {
+ super();
+ }
+
+ public void setThrowable(String throwable) {
+ this.throwable = throwable;
+ }
+
+ public boolean execute(Throwable t) throws BuildException {
+ try {
+ Class c = Thread.currentThread().getContextClassLoader().loadClass(throwable);
+ if (c.isAssignableFrom(t.getClass())) {
+ execute();
+ return true;
+ }
+ return false;
+ }
+ catch (ClassNotFoundException e) {
+ throw new BuildException(e);
+ }
+ }
+ }
+
+
+ private Sequential tryTasks = null;
+ private Vector catchBlocks = new Vector();
+ private Sequential finallyTasks = null;
+ private String property = null;
+ private String reference = null;
+
+ /**
+ * Adds a nested &lt;try&gt; block - one is required, more is
+ * forbidden.
+ */
+ public void addTry(Sequential seq) throws BuildException {
+ if (tryTasks != null) {
+ throw new BuildException("You must not specify more than one <try>");
+ }
+
+ tryTasks = seq;
+ }
+
+ public void addCatch(CatchBlock cb) {
+ catchBlocks.add(cb);
+ }
+
+ /**
+ * Adds a nested &lt;finally&gt; block - at most one is allowed.
+ */
+ public void addFinally(Sequential seq) throws BuildException {
+ if (finallyTasks != null) {
+ throw new BuildException("You must not specify more than one <finally>");
+ }
+
+ finallyTasks = seq;
+ }
+
+ /**
+ * Sets the property attribute.
+ */
+ public void setProperty(String p) {
+ property = p;
+ }
+
+ /**
+ * Sets the reference attribute.
+ */
+ public void setReference(String r) {
+ reference = r;
+ }
+
+ /**
+ * The heart of the task.
+ */
+ public void execute() throws BuildException {
+ if (tryTasks == null) {
+ throw new BuildException("A nested <try> element is required");
+ }
+
+ try {
+ tryTasks.perform();
+ } catch (Throwable e) {
+ if (property != null) {
+ /*
+ * Using setProperty instead of setNewProperty to
+ * be able to compile with Ant < 1.5.
+ */
+ getProject().setProperty(property, e.getMessage());
+ }
+
+ if (reference != null) {
+ getProject().addReference(reference, e);
+ }
+
+ boolean executed = false;
+ Enumeration blocks = catchBlocks.elements();
+ while (blocks.hasMoreElements() && ! executed) {
+ CatchBlock cb = (CatchBlock)blocks.nextElement();
+ executed = cb.execute(e);
+ }
+ } finally {
+ if (finallyTasks != null) {
+ finallyTasks.perform();
+ }
+ }
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/math/Evaluateable.java b/src/java/net/sf/antcontrib/math/Evaluateable.java
new file mode 100644
index 0000000..2e56967
--- /dev/null
+++ b/src/java/net/sf/antcontrib/math/Evaluateable.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+/**
+ * An object which can evaluate to a numeric value.
+ *
+ * @author inger
+ */
+
+
+public interface Evaluateable
+{
+ Number evaluate();
+}
diff --git a/src/java/net/sf/antcontrib/math/Math.java b/src/java/net/sf/antcontrib/math/Math.java
new file mode 100644
index 0000000..984a2ce
--- /dev/null
+++ b/src/java/net/sf/antcontrib/math/Math.java
@@ -0,0 +1,584 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+import org.apache.tools.ant.BuildException;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Utility class for executing calculations.
+ *
+ * @author inger
+ */
+
+
+public class Math
+{
+ public static final Number evaluate(String operation,
+ String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ if (datatype == null)
+ datatype = "double";
+
+ try
+ {
+ operation = operation.toLowerCase();
+
+ Method m = Math.class.getDeclaredMethod(operation,
+ new Class[]{
+ String.class,
+ Boolean.TYPE,
+ operands.getClass()
+ });
+ Number n = (Number) m.invoke(null,
+ new Object[]{
+ datatype,
+ strict ? Boolean.TRUE : Boolean.FALSE,
+ operands
+ });
+
+ return n;
+ }
+ catch (NoSuchMethodException e)
+ {
+ e.printStackTrace();
+ }
+ catch (IllegalAccessException e)
+ {
+ e.printStackTrace();
+ }
+ catch (InvocationTargetException e)
+ {
+ e.getTargetException().printStackTrace();
+ }
+ return null;
+ }
+
+ public static final Number add(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Number result = null;
+
+ Number numbers[] = new Number[operands.length];
+ for (int i = 0; i < operands.length; i++)
+ numbers[i] = operands[i].evaluate();
+
+ if (datatype.equalsIgnoreCase("int"))
+ {
+ int sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i].intValue();
+ result = new Integer(sum);
+ }
+ else if (datatype.equalsIgnoreCase("long"))
+ {
+ long sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i].longValue();
+ result = new Long(sum);
+ }
+ else if (datatype.equalsIgnoreCase("float"))
+ {
+ float sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i].floatValue();
+ result = new Float(sum);
+ }
+ else if (datatype.equalsIgnoreCase("double"))
+ {
+ double sum = 0;
+ for (int i = 0; i < numbers.length; i++)
+ sum += numbers[i].doubleValue();
+ result = new Double(sum);
+ }
+ return result;
+ }
+
+ public static final Number subtract(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Number result = null;
+
+ Number numbers[] = new Number[operands.length];
+ for (int i = 0; i < operands.length; i++)
+ numbers[i] = operands[i].evaluate();
+
+ if (datatype.equalsIgnoreCase("int"))
+ {
+ int sum = numbers[0].intValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum -= numbers[i].intValue();
+ result = new Integer(sum);
+ }
+ else if (datatype.equalsIgnoreCase("long"))
+ {
+ long sum = numbers[0].longValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum -= numbers[i].longValue();
+ result = new Long(sum);
+ }
+ else if (datatype.equalsIgnoreCase("float"))
+ {
+ float sum = numbers[0].floatValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum -= numbers[i].floatValue();
+ result = new Float(sum);
+ }
+ else if (datatype.equalsIgnoreCase("double"))
+ {
+ double sum = numbers[0].doubleValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum -= numbers[i].doubleValue();
+ result = new Double(sum);
+ }
+ return result;
+ }
+
+ public static final Number multiply(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Number result = null;
+
+ Number numbers[] = new Number[operands.length];
+ for (int i = 0; i < operands.length; i++)
+ numbers[i] = operands[i].evaluate();
+
+ if (datatype.equalsIgnoreCase("int"))
+ {
+ int sum = 1;
+ for (int i = 0; i < numbers.length; i++)
+ sum *= numbers[i].intValue();
+ result = new Integer(sum);
+ }
+ else if (datatype.equalsIgnoreCase("long"))
+ {
+ long sum = 1;
+ for (int i = 0; i < numbers.length; i++)
+ sum *= numbers[i].longValue();
+ result = new Long(sum);
+ }
+ else if (datatype.equalsIgnoreCase("float"))
+ {
+ float sum = 1;
+ for (int i = 0; i < numbers.length; i++)
+ sum *= numbers[i].floatValue();
+ result = new Float(sum);
+ }
+ else if (datatype.equalsIgnoreCase("double"))
+ {
+ double sum = 1;
+ for (int i = 0; i < numbers.length; i++)
+ sum *= numbers[i].doubleValue();
+ result = new Double(sum);
+ }
+ return result;
+ }
+
+ public static final Number divide(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Number result = null;
+
+ Number numbers[] = new Number[operands.length];
+ for (int i = 0; i < operands.length; i++)
+ numbers[i] = operands[i].evaluate();
+
+ if (datatype.equalsIgnoreCase("int"))
+ {
+ int sum = numbers[0].intValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum /= numbers[i].intValue();
+ result = new Integer(sum);
+ }
+ else if (datatype.equalsIgnoreCase("long"))
+ {
+ long sum = numbers[0].longValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum /= numbers[i].longValue();
+ result = new Long(sum);
+ }
+ else if (datatype.equalsIgnoreCase("float"))
+ {
+ float sum = numbers[0].floatValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum /= numbers[i].floatValue();
+ result = new Float(sum);
+ }
+ else if (datatype.equalsIgnoreCase("double"))
+ {
+ double sum = numbers[0].doubleValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum /= numbers[i].doubleValue();
+ result = new Double(sum);
+ }
+ return result;
+ }
+
+ public static final Number mod(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Number result = null;
+
+ Number numbers[] = new Number[operands.length];
+ for (int i = 0; i < operands.length; i++)
+ numbers[i] = operands[i].evaluate();
+
+ if (datatype.equalsIgnoreCase("int"))
+ {
+ int sum = numbers[0].intValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum %= numbers[i].intValue();
+ result = new Integer(sum);
+ }
+ else if (datatype.equalsIgnoreCase("long"))
+ {
+ long sum = numbers[0].longValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum %= numbers[i].longValue();
+ result = new Long(sum);
+ }
+ else if (datatype.equalsIgnoreCase("float"))
+ {
+ float sum = numbers[0].floatValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum %= numbers[i].floatValue();
+ result = new Float(sum);
+ }
+ else if (datatype.equalsIgnoreCase("double"))
+ {
+ double sum = numbers[0].doubleValue();
+ for (int i = 1; i < numbers.length; i++)
+ sum %= numbers[i].doubleValue();
+ result = new Double(sum);
+ }
+ return result;
+ }
+
+ public static final Number convert(Number n, String datatype)
+ {
+ if (datatype == null)
+ datatype = "double";
+ if (datatype.equals("int"))
+ return new Integer(n.intValue());
+ if (datatype.equals("long"))
+ return new Long(n.longValue());
+ if (datatype.equals("float"))
+ return new Float(n.floatValue());
+ if (datatype.equals("double"))
+ return new Double(n.doubleValue());
+ throw new BuildException("Invalid datatype.");
+ }
+
+ public static final Number execute(String method,
+ String datatype,
+ boolean strict,
+ Class paramTypes[],
+ Object params[])
+ {
+ try
+ {
+ Class c = null;
+ if (strict)
+ {
+ c = Thread.currentThread().getContextClassLoader().loadClass("java.lang.StrictMath");
+ }
+ else
+ {
+ c = Thread.currentThread().getContextClassLoader().loadClass("java.lang.Math");
+ }
+
+ Method m = c.getDeclaredMethod(method, paramTypes);
+ Number n = (Number) m.invoke(null, params);
+ return convert(n, datatype);
+ }
+ catch (ClassNotFoundException e)
+ {
+ throw new BuildException(e);
+ }
+ catch (NoSuchMethodException e)
+ {
+ throw new BuildException(e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new BuildException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ throw new BuildException(e);
+ }
+ }
+
+ public static final Number random(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return execute("random",
+ datatype,
+ strict,
+ new Class[0],
+ new Object[0]);
+ }
+
+ public static Class getPrimitiveClass(String datatype)
+ {
+ if (datatype == null)
+ return Double.TYPE;
+ if (datatype.equals("int"))
+ return Integer.TYPE;
+ if (datatype.equals("long"))
+ return Long.TYPE;
+ if (datatype.equals("float"))
+ return Float.TYPE;
+ if (datatype.equals("double"))
+ return Double.TYPE;
+ throw new BuildException("Invalid datatype.");
+
+ }
+
+ public static final Number abs(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(), datatype)};
+ Class params[] = new Class[]{getPrimitiveClass(datatype)};
+
+ return execute("abs",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ private static final Number doOneDoubleArg(String operation,
+ String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ "double")};
+ Class params[] = new Class[]{Double.TYPE};
+
+ return execute(operation,
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ public static final Number acos(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("acos", datatype, strict, operands);
+ }
+
+ public static final Number asin(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("asin", datatype, strict, operands);
+ }
+
+ public static final Number atan(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("atan", datatype, strict, operands);
+ }
+
+ public static final Number atan2(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ "double"),
+ convert(operands[1].evaluate(),
+ "double")};
+ Class params[] = new Class[]{Double.TYPE,
+ Double.TYPE};
+
+ return execute("atan2",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ public static final Number sin(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("sin", datatype, strict, operands);
+ }
+
+ public static final Number tan(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("sin", datatype, strict, operands);
+ }
+
+ public static final Number cos(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("cos", datatype, strict, operands);
+ }
+
+ public static final Number ceil(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("ceil", datatype, strict, operands);
+ }
+
+ public static final Number floor(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("floor", datatype, strict, operands);
+ }
+
+ public static final Number exp(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("exp", datatype, strict, operands);
+ }
+
+ public static final Number rint(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("rint", datatype, strict, operands);
+ }
+
+ public static final Number round(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ datatype)};
+ Class params[] = new Class[]{getPrimitiveClass(datatype)};
+
+ return execute("round",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ public static final Number sqrt(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("sqrt", datatype, strict, operands);
+ }
+
+ public static final Number degrees(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return todegrees(datatype, strict, operands);
+ }
+
+ public static final Number todegrees(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("toDegrees", datatype, strict, operands);
+ }
+
+ public static final Number radians(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return toradians(datatype, strict, operands);
+ }
+
+ public static final Number toradians(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ return doOneDoubleArg("toRadians", datatype, strict, operands);
+ }
+
+ public static final Number ieeeremainder(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ "double"),
+ convert(operands[1].evaluate(),
+ "double")};
+ Class params[] = new Class[]{Double.TYPE,
+ Double.TYPE};
+
+ return execute("IEEERemainder",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ public static final Number min(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ datatype),
+ convert(operands[1].evaluate(),
+ datatype)};
+ Class params[] = new Class[]{getPrimitiveClass(datatype),
+ getPrimitiveClass(datatype)};
+
+ return execute("min",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+ public static final Number max(String datatype,
+ boolean strict,
+ Evaluateable operands[])
+ {
+ Object ops[] = new Object[]{convert(operands[0].evaluate(),
+ datatype),
+ convert(operands[1].evaluate(),
+ datatype)};
+ Class params[] = new Class[]{getPrimitiveClass(datatype),
+ getPrimitiveClass(datatype)};
+
+ return execute("max",
+ datatype,
+ strict,
+ params,
+ ops);
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/math/MathTask.java b/src/java/net/sf/antcontrib/math/MathTask.java
new file mode 100644
index 0000000..bdcc12d
--- /dev/null
+++ b/src/java/net/sf/antcontrib/math/MathTask.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.DynamicConfigurator;
+
+/**
+ * Task for mathematical operations.
+ *
+ * @author inger
+ */
+
+
+public class MathTask
+ extends Task
+ implements DynamicConfigurator
+{
+ // storage for result
+ private String result = null;
+ private Operation operation = null;
+ private Operation locOperation = null;
+ private String datatype = null;
+ private boolean strict = false;
+
+ public MathTask()
+ {
+ super();
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ Operation op = locOperation;
+ if (op == null)
+ op = operation;
+
+ Number res = op.evaluate();
+
+ if (datatype != null)
+ res = Math.convert(res, datatype);
+ getProject().setUserProperty(result, res.toString());
+ }
+
+ public void setDynamicAttribute(String s, String s1)
+ throws BuildException {
+ throw new BuildException("No dynamic attributes for this task");
+ }
+
+ public Object createDynamicElement(String name)
+ throws BuildException {
+ Operation op = new Operation();
+ op.setOperation(name);
+ operation = op;
+ return op;
+ }
+
+ public void setResult(String result)
+ {
+ this.result = result;
+ }
+
+ public void setDatatype(String datatype)
+ {
+ this.datatype = datatype;
+ }
+
+ public void setStrict(boolean strict)
+ {
+ this.strict = strict;
+ }
+
+ private Operation getLocalOperation()
+ {
+ if (locOperation == null)
+ {
+ locOperation = new Operation();
+ locOperation.setDatatype(datatype);
+ locOperation.setStrict(strict);
+ }
+ return locOperation;
+ }
+
+ public void setOperation(String operation)
+ {
+ getLocalOperation().setOperation(operation);
+ }
+
+ public void setDataType(String dataType)
+ {
+ getLocalOperation().setDatatype(dataType);
+ }
+
+ public void setOperand1(String operand1)
+ {
+ Numeric n = new Numeric();
+ n.setValue(operand1);
+ getLocalOperation().addConfiguredNumeric(n);
+ }
+
+ public void setOperand2(String operand2)
+ {
+ Numeric n = new Numeric();
+ n.setValue(operand2);
+ getLocalOperation().addConfiguredNumeric(n);
+ }
+
+ public Operation createOperation()
+ {
+ if (locOperation != null || operation != null)
+ throw new BuildException("Doh!!!");
+ this.operation = new Operation();
+ this.operation.setStrict(strict);
+ this.operation.setDatatype(datatype);
+ return this.operation;
+ }
+
+ // conform to old task
+ public Operation createOp()
+ {
+ return createOperation();
+ }
+}
diff --git a/src/java/net/sf/antcontrib/math/Numeric.java b/src/java/net/sf/antcontrib/math/Numeric.java
new file mode 100644
index 0000000..1164e14
--- /dev/null
+++ b/src/java/net/sf/antcontrib/math/Numeric.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+import org.apache.tools.ant.BuildException;
+
+
+/**
+ * A numeric value that implements Evaluateable.
+ *
+ * @author inger
+ */
+
+
+public class Numeric
+ implements Evaluateable
+{
+ private String datatype;
+ private String value;
+
+ /**
+ * Set the value for this number. This string must parse to the set
+ * datatype, for example, setting value to "7.992" and datatype to INT
+ * will cause a number format exception to be thrown. Supports two special
+ * numbers, "E" and "PI".
+ *
+ * @param value the value for this number
+ */
+ public void setValue(String value)
+ {
+ if (value.equals("E"))
+ value = String.valueOf(java.lang.Math.E);
+ else if (value.equals("PI"))
+ value = String.valueOf(java.lang.Math.PI);
+ this.value = value;
+ }
+
+ /**
+ * @return the value for this number as a Number. Cast as appropriate to
+ * Integer, Long, Float, or Double.
+ */
+ public Number evaluate()
+ {
+ if (datatype == null)
+ datatype = "double";
+ if (datatype.equals("int"))
+ return new Integer(value);
+ if (datatype.equals("long"))
+ return new Long(value);
+ if (datatype.equals("float"))
+ return new Float(value);
+ if (datatype.equals("double"))
+ return new Double(value);
+ throw new BuildException("Invalid datatype.");
+ }
+
+ /**
+ * Sets the datatype of this number. Allowed values are
+ * "int", "long", "float", or "double".
+ */
+ public void setDatatype(String p)
+ {
+ datatype = p;
+ }
+
+ /**
+ * @return the datatype as one of the defined types.
+ */
+ public String getDatatype()
+ {
+ if (datatype == null)
+ datatype = "double";
+ return datatype;
+ }
+
+ public String toString()
+ {
+ return "Numeric[value=" + value
+ + ";datatype=" + datatype
+ + "]";
+ }
+}
diff --git a/src/java/net/sf/antcontrib/math/Operation.java b/src/java/net/sf/antcontrib/math/Operation.java
new file mode 100644
index 0000000..8727a10
--- /dev/null
+++ b/src/java/net/sf/antcontrib/math/Operation.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DynamicConfigurator;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * Class to represent a mathematical operation.
+ *
+ * @author inger
+ */
+
+
+public class Operation
+ implements Evaluateable, DynamicConfigurator {
+ private String operation = "add";
+ private Vector operands = new Vector();
+ private String datatype = "double";
+ private boolean strict = false;
+
+ private boolean hasLocalOperands = false;
+ private Numeric localOperands[] = new Numeric[5];
+
+ public void setDynamicAttribute(String s, String s1)
+ throws BuildException {
+ throw new BuildException("no dynamic attributes for this element");
+ }
+
+ public Object createDynamicElement(String name)
+ throws BuildException {
+ Operation op = new Operation();
+ op.setOperation(name);
+ operands.add(op);
+ return op;
+ }
+
+ private void setLocalOperand(String value, int index) {
+ hasLocalOperands = true;
+ localOperands[index - 1] = new Numeric();
+ localOperands[index - 1].setValue(value);
+ }
+
+ public void setArg1(String value) {
+ setLocalOperand(value, 1);
+ }
+
+ public void setArg2(String value) {
+ setLocalOperand(value, 2);
+ }
+
+ public void setArg3(String value) {
+ setLocalOperand(value, 3);
+ }
+
+ public void setArg4(String value) {
+ setLocalOperand(value, 4);
+ }
+
+ public void setArg5(String value) {
+ setLocalOperand(value, 5);
+ }
+
+ public void addConfiguredNumeric(Numeric numeric) {
+ if (hasLocalOperands)
+ throw new BuildException("Cannot combine operand attributes with subelements");
+
+ operands.add(numeric);
+ }
+
+ public void addConfiguredOperation(Operation operation) {
+ if (hasLocalOperands)
+ throw new BuildException("Cannot combine operand attributes with subelements");
+
+ operands.add(operation);
+ }
+
+ public void addConfiguredNum(Numeric numeric) {
+ if (hasLocalOperands)
+ throw new BuildException("Cannot combine operand attributes with subelements");
+
+ operands.add(numeric);
+ }
+
+ public void addConfiguredOp(Operation operation) {
+ if (hasLocalOperands)
+ throw new BuildException("Cannot combine operand attributes with subelements");
+
+ operands.add(operation);
+ }
+
+ public void setOp(String operation) {
+ setOperation(operation);
+ }
+
+ public void setOperation(String operation) {
+ if (operation.equals("+"))
+ this.operation = "add";
+ else if (operation.equals("-"))
+ this.operation = "subtract";
+ else if (operation.equals("*"))
+ this.operation = "multiply";
+ else if (operation.equals("/"))
+ this.operation = "divide";
+ else if (operation.equals("%"))
+ this.operation = "mod";
+ else
+ this.operation = operation;
+ }
+
+ public void setDatatype(String datatype) {
+ this.datatype = datatype;
+ }
+
+ public void setStrict(boolean strict) {
+ this.strict = strict;
+ }
+
+ public Number evaluate() {
+ Evaluateable ops[] = null;
+
+ if (hasLocalOperands) {
+ List localOps = new ArrayList();
+ for (int i = 0; i < localOperands.length; i++) {
+ if (localOperands[i] != null)
+ localOps.add(localOperands[i]);
+ }
+
+ ops = (Evaluateable[]) localOps.toArray(new Evaluateable[localOps.size()]);
+ }
+ else {
+ ops = (Evaluateable[]) operands.toArray(new Evaluateable[operands.size()]);
+ }
+
+ return Math.evaluate(operation,
+ datatype,
+ strict,
+ ops);
+ }
+
+ public String toString() {
+ return "Operation[operation=" + operation
+ + ";datatype=" + datatype
+ + ";strict=" + strict
+ + ";localoperands=" + Arrays.asList(localOperands)
+ + ";operands=" + operands
+ + "]";
+ }
+}
diff --git a/src/java/net/sf/antcontrib/net/PostTask.java b/src/java/net/sf/antcontrib/net/PostTask.java
new file mode 100644
index 0000000..4f1d5b0
--- /dev/null
+++ b/src/java/net/sf/antcontrib/net/PostTask.java
@@ -0,0 +1,751 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.net;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.HttpURLConnection;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+import java.rmi.server.UID;
+
+import java.util.*;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+
+/**
+ * This task does an http post. Name/value pairs for the post can be set in
+ * either or both of two ways, by nested Prop elements and/or by a file
+ * containing properties. Nested Prop elements are automatically configured by
+ * Ant. Properties from a file are configured by code borrowed from Property so
+ * all Ant property constructs (like ${somename}) are resolved prior to the
+ * post. This means that a file can be set up in advance of running the build
+ * and the appropriate property values will be filled in at run time.
+ *
+ * @author Dale Anson, [email protected]
+ * @version $Revision: 1.11 $
+ */
+public class PostTask extends Task {
+
+ /** Storage for name/value pairs to send. */
+ private Hashtable props = new Hashtable();
+ /** URL to send the name/value pairs to. */
+ private URL to = null;
+ /** File to read name/value pairs from. */
+ private File propsFile = null;
+ /** storage for Ant properties */
+ private String textProps = null;
+ /** encoding to use for the name/value pairs */
+ private String encoding = "UTF-8";
+ /** where to store the server response */
+ private File log = null;
+ /** append to the log? */
+ private boolean append = true;
+ /** verbose? */
+ private boolean verbose = true;
+ /** want to keep the server response? */
+ private boolean wantResponse = true;
+ /** store output in a property */
+ private String property = null;
+
+ /** how long to wait for a response from the server */
+ private long maxwait = 180000; // units for maxwait is milliseconds
+ /** fail on error? */
+ private boolean failOnError = false;
+
+ // storage for cookies
+ private static Hashtable cookieStorage = new Hashtable();
+
+ /** connection to the server */
+ private URLConnection connection = null;
+ /** for thread handling */
+ private Thread currentRunner = null;
+
+
+
+ /**
+ * Set the url to post to. Required.
+ *
+ * @param name the url to post to.
+ */
+ public void setTo( URL name ) {
+ to = name;
+ }
+
+
+ /**
+ * Set the name of a file to read a set of properties from.
+ *
+ * @param f the file
+ */
+ public void setFile( File f ) {
+ propsFile = f;
+ }
+
+
+ /**
+ * Set the name of a file to save the response to. Optional. Ignored if
+ * "want response" is false.
+ *
+ * @param f the file
+ */
+ public void setLogfile( File f ) {
+ log = f;
+ }
+
+
+ /**
+ * Should the log file be appended to or overwritten? Default is true,
+ * append to the file.
+ *
+ * @param b append or not
+ */
+ public void setAppend( boolean b ) {
+ append = b;
+ }
+
+
+ /**
+ * If true, progress messages and returned data from the post will be
+ * displayed. Default is true.
+ *
+ * @param b true = verbose
+ */
+ public void setVerbose( boolean b ) {
+ verbose = b;
+ }
+
+
+ /**
+ * Default is true, get the response from the post. Can be set to false for
+ * "fire and forget" messages.
+ *
+ * @param b print/log server response
+ */
+ public void setWantresponse( boolean b ) {
+ wantResponse = b;
+ }
+
+ /**
+ * Set the name of a property to save the response to. Optional. Ignored if
+ * "wantResponse" is false.
+ * @param name the name to use for the property
+ */
+ public void setProperty( String name ) {
+ property = name;
+ }
+
+ /**
+ * Sets the encoding of the outgoing properties, default is UTF-8.
+ *
+ * @param encoding The new encoding value
+ */
+ public void setEncoding( String encoding ) {
+ this.encoding = encoding;
+ }
+
+
+ /**
+ * How long to wait on the remote server. As a post is generally a two part
+ * process (sending and receiving), maxwait is applied separately to each
+ * part, that is, if 180 is passed as the wait parameter, this task will
+ * spend at most 3 minutes to connect to the remote server and at most
+ * another 3 minutes waiting on a response after the post has been sent.
+ * This means that the wait period could total as much as 6 minutes (or 360
+ * seconds). <p>
+ *
+ * The default wait period is 3 minutes (180 seconds).
+ *
+ * @param wait time to wait in seconds, set to 0 to wait forever.
+ */
+ public void setMaxwait( int wait ) {
+ maxwait = wait * 1000;
+ }
+
+
+ /**
+ * Should the build fail if the post fails?
+ *
+ * @param fail true = fail the build, default is false
+ */
+ public void setFailonerror( boolean fail ) {
+ failOnError = fail;
+ }
+
+ /**
+ * Adds a name/value pair to post. Optional.
+ *
+ * @param p A property pair to send as part of the post.
+ * @exception BuildException When name and/or value are missing.
+ */
+ public void addConfiguredProp( Prop p ) throws BuildException {
+ String name = p.getName();
+ if ( name == null ) {
+ throw new BuildException( "name is null", getLocation() );
+ }
+ String value = p.getValue();
+ if ( value == null ) {
+ value = getProject().getProperty( name );
+ }
+ if ( value == null ) {
+ throw new BuildException( "value is null", getLocation() );
+ }
+ props.put( name, value );
+ }
+
+
+ /**
+ * Adds a feature to the Text attribute of the PostTask object
+ *
+ * @param text The feature to be added to the Text attribute
+ */
+ public void addText( String text ) {
+ textProps = text;
+ }
+
+
+ /**
+ * Do the post.
+ *
+ * @exception BuildException On any error.
+ */
+ public void execute() throws BuildException {
+ if ( to == null ) {
+ throw new BuildException( "'to' attribute is required", getLocation() );
+ }
+ final String content = getContent();
+ try {
+ if ( verbose )
+ log( "Opening connection for post to " + to.toString() + "..." );
+
+ // do the POST
+ Thread runner =
+ new Thread() {
+ public void run() {
+ DataOutputStream out = null;
+ try {
+ // set the url connection properties
+ connection = to.openConnection();
+ connection.setDoInput( true );
+ connection.setDoOutput( true );
+ connection.setUseCaches( false );
+ connection.setRequestProperty(
+ "Content-Type",
+ "application/x-www-form-urlencoded" );
+
+ // check if there are cookies to be included
+ for ( Iterator it = cookieStorage.keySet().iterator(); it.hasNext(); ) {
+ StringBuffer sb = new StringBuffer();
+ Object name = it.next();
+ if ( name != null ) {
+ String key = name.toString();
+ Cookie cookie = ( Cookie ) cookieStorage.get( name );
+ if ( to.getPath().startsWith( cookie.getPath() ) ) {
+ connection.addRequestProperty( "Cookie", cookie.toString() );
+ }
+ }
+ }
+
+ // do the post
+ if ( verbose ) {
+ log( "Connected, sending data..." );
+ }
+ out = new DataOutputStream( connection.getOutputStream() );
+ if ( verbose ) {
+ log( content );
+ }
+ out.writeBytes( content );
+ out.flush();
+ if ( verbose ) {
+ log( "Data sent." );
+ }
+ }
+ catch ( Exception e ) {
+ if ( failOnError ) {
+ throw new BuildException( e, getLocation() );
+ }
+ }
+ finally {
+ try {
+ out.close();
+ }
+ catch ( Exception e ) {
+ // ignored
+ }
+ }
+ }
+ }
+ ;
+ runner.start();
+ runner.join( maxwait );
+ if ( runner.isAlive() ) {
+ runner.interrupt();
+ if ( failOnError ) {
+ throw new BuildException( "maxwait exceeded, unable to send data", getLocation() );
+ }
+ return ;
+ }
+
+ // read the response, if any, optionally writing it to a file
+ if ( wantResponse ) {
+ if ( verbose ) {
+ log( "Waiting for response..." );
+ }
+ runner =
+ new Thread() {
+ public void run() {
+ PrintWriter fw = null;
+ StringWriter sw = null;
+ PrintWriter pw = null;
+ BufferedReader in = null;
+ try {
+ if ( connection instanceof HttpURLConnection ) {
+ // read and store cookies
+ Map map = ( ( HttpURLConnection ) connection ).getHeaderFields();
+ for ( Iterator it = map.keySet().iterator(); it.hasNext(); ) {
+ String name = ( String ) it.next();
+ if ( name != null && name.equals( "Set-Cookie" ) ) {
+ List cookies = ( List ) map.get( name );
+ for ( Iterator c = cookies.iterator(); c.hasNext(); ) {
+ String raw = ( String ) c.next();
+ Cookie cookie = new Cookie( raw );
+ cookieStorage.put( cookie.getId(), cookie );
+ }
+ }
+ }
+
+ // maybe log response headers
+ if ( verbose ) {
+ log( String.valueOf( ( ( HttpURLConnection ) connection ).getResponseCode() ) );
+ log( ( ( HttpURLConnection ) connection ).getResponseMessage() );
+ StringBuffer sb = new StringBuffer();
+ map = ( ( HttpURLConnection ) connection ).getHeaderFields();
+ for ( Iterator it = map.keySet().iterator(); it.hasNext(); ) {
+ String name = ( String ) it.next();
+ sb.append( name ).append( "=" );
+ List values = ( List ) map.get( name );
+ if ( values != null ) {
+ if ( values.size() == 1 )
+ sb.append( values.get( 0 ) );
+ else if ( values.size() > 1 ) {
+ sb.append( "[" );
+ for ( Iterator v = values.iterator(); v.hasNext(); ) {
+ sb.append( v.next() ).append( "," );
+ }
+ sb.append( "]" );
+ }
+ }
+ sb.append( "\n" );
+ log( sb.toString() );
+ }
+ }
+ }
+ in = new BufferedReader(
+ new InputStreamReader( connection.getInputStream() ) );
+ if ( log != null ) {
+ // user wants output stored to a file
+ fw = new PrintWriter( new FileWriter( log, append ) );
+ }
+ if ( property != null ) {
+ // user wants output stored in a property
+ sw = new StringWriter();
+ pw = new PrintWriter( sw );
+ }
+ String line;
+ while ( null != ( ( line = in.readLine() ) ) ) {
+ if ( currentRunner != this ) {
+ break;
+ }
+ if ( verbose ) {
+ log( line );
+ }
+ if ( fw != null ) {
+ // write response to a file
+ fw.println( line );
+ }
+ if ( pw != null ) {
+ // write response to a property
+ pw.println( line );
+ }
+ }
+ }
+ catch ( Exception e ) {
+ //e.printStackTrace();
+ if ( failOnError ) {
+ throw new BuildException( e, getLocation() );
+ }
+ }
+ finally {
+ try {
+ in.close();
+ }
+ catch ( Exception e ) {
+ // ignored
+ }
+ try {
+ if ( fw != null ) {
+ fw.flush();
+ fw.close();
+ }
+ }
+ catch ( Exception e ) {
+ // ignored
+ }
+ }
+ if ( property != null && sw != null ) {
+ // save property
+ getProject().setProperty( property, sw.toString() );
+ }
+ }
+ };
+ currentRunner = runner;
+ runner.start();
+ runner.join( maxwait );
+ if ( runner.isAlive() ) {
+ currentRunner = null;
+ runner.interrupt();
+ if ( failOnError ) {
+ throw new BuildException( "maxwait exceeded, unable to receive data", getLocation() );
+ }
+ }
+ }
+ if ( verbose )
+ log( "Post complete." );
+ }
+ catch ( Exception e ) {
+ if ( failOnError ) {
+ throw new BuildException( e );
+ }
+ }
+ }
+
+
+ /**
+ * Borrowed from Property -- load variables from a file
+ *
+ * @param file file to load
+ * @exception BuildException Description of the Exception
+ */
+ private void loadFile( File file ) throws BuildException {
+ Properties fileprops = new Properties();
+ try {
+ if ( file.exists() ) {
+ FileInputStream fis = new FileInputStream( file );
+ try {
+ fileprops.load( fis );
+ }
+ finally {
+ if ( fis != null ) {
+ fis.close();
+ }
+ }
+ addProperties( fileprops );
+ }
+ else {
+ log( "Unable to find property file: " + file.getAbsolutePath(),
+ Project.MSG_VERBOSE );
+ }
+ log( "Post complete." );
+ }
+ catch ( Exception e ) {
+ if ( failOnError ) {
+ throw new BuildException( e );
+ }
+ }
+ }
+
+
+ /**
+ * Builds and formats the message to send to the server. Message is UTF-8
+ * encoded unless encoding has been explicitly set.
+ *
+ * @return the message to send to the server.
+ */
+ private String getContent() {
+ if ( propsFile != null ) {
+ loadFile( propsFile );
+ }
+
+ if ( textProps != null ) {
+ loadTextProps( textProps );
+ }
+
+ StringBuffer content = new StringBuffer();
+ try {
+ Enumeration en = props.keys();
+ while ( en.hasMoreElements() ) {
+ String name = ( String ) en.nextElement();
+ String value = ( String ) props.get( name );
+ content.append( URLEncoder.encode( name, encoding ) );
+ content.append( "=" );
+ content.append( URLEncoder.encode( value, encoding ) );
+ if ( en.hasMoreElements() ) {
+ content.append( "&" );
+ }
+ }
+ }
+ catch ( IOException ex ) {
+ if ( failOnError ) {
+ throw new BuildException( ex, getLocation() );
+ }
+ }
+ return content.toString();
+ }
+
+
+ /**
+ * Description of the Method
+ *
+ * @param tp
+ */
+ private void loadTextProps( String tp ) {
+ Properties p = new Properties();
+ Project project = getProject();
+ StringTokenizer st = new StringTokenizer( tp, "$" );
+ while ( st.hasMoreTokens() ) {
+ String token = st.nextToken();
+ int start = token.indexOf( "{" );
+ int end = token.indexOf( "}" );
+ if ( start > -1 && end > -1 && end > start ) {
+ String name = token.substring( start + 1, end - start );
+ String value = project.getProperty( name );
+ if ( value != null )
+ p.setProperty( name, value );
+ }
+ }
+ addProperties( p );
+ }
+
+
+ /**
+ * Borrowed from Property -- iterate through a set of properties, resolve
+ * them, then assign them
+ *
+ * @param fileprops The feature to be added to the Properties attribute
+ */
+ private void addProperties( Properties fileprops ) {
+ resolveAllProperties( fileprops );
+ Enumeration e = fileprops.keys();
+ while ( e.hasMoreElements() ) {
+ String name = ( String ) e.nextElement();
+ String value = fileprops.getProperty( name );
+ props.put( name, value );
+ }
+ }
+
+
+ /**
+ * Borrowed from Property -- resolve properties inside a properties
+ * hashtable
+ *
+ * @param fileprops Description of the Parameter
+ * @exception BuildException Description of the Exception
+ */
+ private void resolveAllProperties( Properties fileprops ) throws BuildException {
+ for ( Enumeration e = fileprops.keys(); e.hasMoreElements(); ) {
+ String name = ( String ) e.nextElement();
+ String value = fileprops.getProperty( name );
+
+ boolean resolved = false;
+ while ( !resolved ) {
+ Vector fragments = new Vector();
+ Vector propertyRefs = new Vector();
+ /// this is the Ant 1.5 way of doing it. The Ant 1.6 PropertyHelper
+ /// should be used -- eventually.
+ ProjectHelper.parsePropertyString( value, fragments,
+ propertyRefs );
+
+ resolved = true;
+ if ( propertyRefs.size() != 0 ) {
+ StringBuffer sb = new StringBuffer();
+ Enumeration i = fragments.elements();
+ Enumeration j = propertyRefs.elements();
+ while ( i.hasMoreElements() ) {
+ String fragment = ( String ) i.nextElement();
+ if ( fragment == null ) {
+ String propertyName = ( String ) j.nextElement();
+ if ( propertyName.equals( name ) ) {
+ throw new BuildException( "Property " + name
+ + " was circularly "
+ + "defined." );
+ }
+ fragment = getProject().getProperty( propertyName );
+ if ( fragment == null ) {
+ if ( fileprops.containsKey( propertyName ) ) {
+ fragment = fileprops.getProperty( propertyName );
+ resolved = false;
+ }
+ else {
+ fragment = "${" + propertyName + "}";
+ }
+ }
+ }
+ sb.append( fragment );
+ }
+ value = sb.toString();
+ fileprops.put( name, value );
+ }
+ }
+ }
+ }
+
+ /**
+ * Represents a cookie. See RFC 2109 and 2965.
+ */
+ public class Cookie {
+ private String name;
+ private String value;
+ private String domain;
+ private String path = "/";
+ private String id;
+
+ /**
+ * @param raw the raw string abstracted from the header of an http response
+ * for a single cookie.
+ */
+ public Cookie( String raw ) {
+ String[] args = raw.split( "[;]" );
+ for ( int i = 0; i < args.length; i++ ) {
+ String part = args[ i ];
+ int eq_index = part.indexOf("=");
+ if (eq_index == -1)
+ continue;
+ String first_part = part.substring(0, eq_index).trim();
+ String second_part = part.substring(eq_index + 1);
+ if ( i == 0 ) {
+ name = first_part;
+ value = second_part;
+ }
+ else if ( first_part.equalsIgnoreCase( "Path" ) )
+ path = second_part;
+ else if ( first_part.equalsIgnoreCase( "Domain" ) )
+ domain = second_part;
+ }
+ if (name == null)
+ throw new IllegalArgumentException("Raw cookie does not contain a cookie name.");
+ if (path == null)
+ path = "/";
+ setId(path, name);
+ }
+
+ /**
+ * @param name name of the cookie
+ * @param value the value of the cookie
+ */
+ public Cookie( String name, String value ) {
+ if (name == null)
+ throw new IllegalArgumentException("Cookie name may not be null.");
+
+ this.name = name;
+ this.value = value;
+ setId(name);
+ }
+
+ /**
+ * @return the id of the cookie, used internally by Post to store the cookie
+ * in a hashtable.
+ */
+ public String getId() {
+ if (id == null)
+ setId(path, name);
+ return id.toString();
+ }
+
+ private void setId(String name) {
+ setId(path, name);
+ }
+
+ private void setId(String path, String name) {
+ if (name == null)
+ name = "";
+ id = path + name;
+ }
+
+ /**
+ * @return the name of the cookie
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return the value of the cookie
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * @param domain the domain of the cookie
+ */
+ public void setDomain( String domain ) {
+ this.domain = domain;
+ }
+
+ /**
+ * @return the domain of the cookie
+ */
+ public String getDomain() {
+ return domain;
+ }
+
+ /**
+ * @param path the path of the cookie
+ */
+ public void setPath( String path ) {
+ this.path = path;
+ }
+
+ /**
+ * @return the path of the cookie
+ */
+ public String getPath() {
+ return path;
+ }
+
+ /**
+ * @return a Cookie formatted as a Cookie Version 1 string. The returned
+ * string is suitable for including with an http request.
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append( name ).append( "=" ).append( value ).append( ";" );
+ if ( domain != null )
+ sb.append( "Domain=" ).append( domain ).append( ";" );
+ if ( path != null )
+ sb.append( "Path=" ).append( path ).append( ";" );
+ sb.append( "Version=\"1\";" );
+ return sb.toString();
+ }
+ }
+}
+
diff --git a/src/java/net/sf/antcontrib/net/Prop.java b/src/java/net/sf/antcontrib/net/Prop.java
new file mode 100644
index 0000000..8e4fdcb
--- /dev/null
+++ b/src/java/net/sf/antcontrib/net/Prop.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.net;
+
+/**
+ * Simple bean to represent a name/value pair.
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author Dale Anson, [email protected]
+ * @version $Revision: 1.3 $
+ */
+public class Prop {
+ private String name = null;
+ private String value = null;
+ public void setName( String name ) {
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setValue( String value ) {
+ this.value = value;
+ }
+ public String getValue() {
+ return value;
+ }
+}
+
diff --git a/src/java/net/sf/antcontrib/perf/AntPerformanceListener.java b/src/java/net/sf/antcontrib/perf/AntPerformanceListener.java
new file mode 100644
index 0000000..ba8ea5b
--- /dev/null
+++ b/src/java/net/sf/antcontrib/perf/AntPerformanceListener.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.perf;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+import org.apache.tools.ant.*;
+
+/**
+ * This BuildListener keeps track of the total time it takes for each target and
+ * task to execute, then prints out the totals when the build is finished. This
+ * can help pinpoint the areas where a build is taking a lot of time so
+ * optimization efforts can focus where they'll do the most good. Execution times
+ * are grouped by targets and tasks, and are sorted from fastest running to
+ * slowest running.
+ *
+ * Output can be saved to a file by setting a property in Ant. Set
+ * "performance.log" to the name of a file. This can be set either on the
+ * command line with the -D option (-Dperformance.log=/tmp/performance.log)
+ * or in the build file itself (<property name="performance.log"
+ * location="/tmp/performance.log"/>).
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author Dale Anson, [email protected]
+ * @version $Revision: 1.5 $
+ */
+public class AntPerformanceListener implements BuildListener {
+
+ private HashMap targetStats = new HashMap(); // key is Target, value is StopWatch
+ private HashMap taskStats = new HashMap(); // key is Task, value is StopWatch
+ private StopWatch master = null;
+ private long start_time = 0;
+
+ /**
+ * Starts a 'running total' stopwatch.
+ */
+ public void buildStarted( BuildEvent be ) {
+ master = new StopWatch();
+ start_time = master.start();
+ }
+
+ /**
+ * Sorts and prints the results.
+ */
+ public void buildFinished( BuildEvent be ) {
+ long stop_time = master.stop();
+
+ // sort targets, key is StopWatch, value is Target
+ TreeMap sortedTargets = new TreeMap( new StopWatchComparator() );
+ Iterator it = targetStats.keySet().iterator();
+ while ( it.hasNext() ) {
+ Object key = it.next();
+ Object value = targetStats.get( key );
+ sortedTargets.put( value, key );
+ }
+
+ // sort tasks, key is StopWatch, value is Task
+ TreeMap sortedTasks = new TreeMap( new StopWatchComparator() );
+ it = taskStats.keySet().iterator();
+ while ( it.hasNext() ) {
+ Object key = it.next();
+ Object value = taskStats.get( key );
+ sortedTasks.put( value, key );
+ }
+
+ // print the sorted results
+ StringBuffer msg = new StringBuffer();
+ String lSep = System.getProperty( "line.separator" );
+ msg.append( lSep ).append("Statistics:").append( lSep );
+ msg.append( "-------------- Target Results ---------------------" ).append( lSep );
+ it = sortedTargets.keySet().iterator();
+ while ( it.hasNext() ) {
+ StopWatch key = ( StopWatch ) it.next();
+ StringBuffer sb = new StringBuffer();
+ Target target = ( Target ) sortedTargets.get( key );
+ if (target != null) {
+ Project p = target.getProject();
+ if (p != null && p.getName() != null)
+ sb.append( p.getName() ).append( "." );
+ String total = format( key.total() );
+ String target_name = target.getName();
+ if (target_name == null || target_name.length() == 0)
+ target_name = "<implicit>";
+ sb.append( target_name ).append( ": " ).append( total );
+ }
+ msg.append( sb.toString() ).append( lSep );
+ }
+ msg.append( lSep );
+ msg.append( "-------------- Task Results -----------------------" ).append( lSep );
+ it = sortedTasks.keySet().iterator();
+ while ( it.hasNext() ) {
+ StopWatch key = ( StopWatch ) it.next();
+ Task task = ( Task ) sortedTasks.get( key );
+ StringBuffer sb = new StringBuffer();
+ Target target = task.getOwningTarget();
+ if (target != null) {
+ Project p = target.getProject();
+ if (p != null && p.getName() != null)
+ sb.append( p.getName() ).append( "." );
+ String target_name = target.getName();
+ if (target_name == null || target_name.length() == 0)
+ target_name = "<implicit>";
+ sb.append( target_name ).append( "." );
+ }
+ sb.append( task.getTaskName() ).append( ": " ).append( format( key.total() ) );
+ msg.append( sb.toString() ).append( lSep );
+ }
+
+ msg.append( lSep );
+ msg.append( "-------------- Totals -----------------------------" ).append( lSep );
+ SimpleDateFormat format = new SimpleDateFormat( "EEE, d MMM yyyy HH:mm:ss.SSS" );
+ msg.append( "Start time: " + format.format( new Date( start_time ) ) ).append( lSep );
+ msg.append( "Stop time: " + format.format( new Date( stop_time ) ) ).append( lSep );
+ msg.append( "Total time: " + format( master.total() ) ).append( lSep );
+ System.out.println( msg.toString() );
+
+ // write stats to file?
+ Project p = be.getProject();
+ File outfile = null;
+ if ( p != null ) {
+ String f = p.getProperty( "performance.log" );
+ if ( f != null )
+ outfile = new File( f );
+ }
+ if ( outfile != null ) {
+ try {
+ FileWriter fw = new FileWriter( outfile );
+ fw.write( msg.toString() );
+ fw.flush();
+ fw.close();
+ System.out.println( "Wrote stats to: " + outfile.getAbsolutePath() + lSep);
+ }
+ catch ( Exception e ) {
+ // ignored
+ }
+ }
+
+ // reset the stats registers
+
+ targetStats = new HashMap();
+ taskStats = new HashMap();
+ }
+
+ /**
+ * Formats the milliseconds from a StopWatch into decimal seconds.
+ */
+ private String format( long ms ) {
+ String total = String.valueOf( ms );
+ String frontpad = "000";
+ int pad_length = 3 - total.length();
+ if ( pad_length >= 0 )
+ total = "0." + frontpad.substring( 0, pad_length ) + total;
+ else {
+ total = total.substring( 0, total.length() - 3 ) + "." + total.substring( total.length() - 3 );
+ }
+ return total + " sec";
+ }
+
+ /**
+ * Start timing the given target.
+ */
+ public void targetStarted( BuildEvent be ) {
+ StopWatch sw = new StopWatch();
+ sw.start();
+ targetStats.put( be.getTarget(), sw );
+ }
+
+ /**
+ * Stop timing the given target.
+ */
+ public void targetFinished( BuildEvent be ) {
+ StopWatch sw = ( StopWatch ) targetStats.get( be.getTarget() );
+ sw.stop();
+ }
+
+ /**
+ * Start timing the given task.
+ */
+ public void taskStarted( BuildEvent be ) {
+ StopWatch sw = new StopWatch();
+ sw.start();
+ taskStats.put( be.getTask(), sw );
+ }
+
+ /**
+ * Stop timing the given task.
+ */
+ public void taskFinished( BuildEvent be ) {
+ StopWatch sw = ( StopWatch ) taskStats.get( be.getTask() );
+ if (sw != null)
+ sw.stop();
+ }
+
+ /**
+ * no-op
+ */
+ public void messageLogged( BuildEvent be ) {
+ // does nothing
+ }
+
+ /**
+ * Compares the total times for two StopWatches.
+ */
+ public class StopWatchComparator implements Comparator {
+ /**
+ * Compares the total times for two StopWatches.
+ */
+ public int compare( Object o1, Object o2 ) {
+ StopWatch a = ( StopWatch ) o1;
+ StopWatch b = ( StopWatch ) o2;
+ if ( a.total() < b.total() )
+ return -1;
+ else if ( a.total() == b.total() )
+ return 0;
+ else
+ return 1;
+ }
+ }
+
+ /**
+ * A stopwatch, useful for 'quick and dirty' performance testing.
+ * @author Dale Anson
+ * @version $Revision: 1.5 $
+ */
+ public class StopWatch {
+
+ /**
+ * storage for start time
+ */
+ private long _start_time = 0;
+ /**
+ * storage for stop time
+ */
+ private long _stop_time = 0;
+
+ /**
+ * cumulative elapsed time
+ */
+ private long _total_time = 0;
+
+ /**
+ * Starts the stopwatch.
+ */
+ public StopWatch() {
+ start();
+ }
+
+ /**
+ * Starts/restarts the stopwatch.
+ *
+ * @return the start time, the long returned System.currentTimeMillis().
+ */
+ public long start() {
+ _start_time = System.currentTimeMillis();
+ return _start_time;
+ }
+
+ /**
+ * Stops the stopwatch.
+ *
+ * @return the stop time, the long returned System.currentTimeMillis().
+ */
+ public long stop() {
+ long stop_time = System.currentTimeMillis();
+ _total_time += stop_time - _start_time;
+ _start_time = 0;
+ _stop_time = 0;
+ return stop_time;
+ }
+
+ /**
+ * Total cumulative elapsed time.
+ *
+ * @return the total time
+ */
+ public long total() {
+ return _total_time;
+ }
+
+ /**
+ * Elapsed time, difference between the last start time and now.
+ *
+ * @return the elapsed time
+ */
+ public long elapsed() {
+ return System.currentTimeMillis() - _start_time;
+ }
+ }
+
+ // quick test for the formatter
+ public static void main ( String[] args ) {
+ AntPerformanceListener apl = new AntPerformanceListener();
+
+ System.out.println( apl.format( 1 ) );
+ System.out.println( apl.format( 10 ) );
+ System.out.println( apl.format( 100 ) );
+ System.out.println( apl.format( 1000 ) );
+ System.out.println( apl.format( 100000 ) );
+ System.out.println( apl.format( 1000000 ) );
+ System.out.println( apl.format( 10000000 ) );
+ System.out.println( apl.format( 100000000 ) );
+ System.out.println( apl.format( 1000000000 ) );
+ }
+}
diff --git a/src/java/net/sf/antcontrib/perf/StopWatch.java b/src/java/net/sf/antcontrib/perf/StopWatch.java
new file mode 100644
index 0000000..ddb3324
--- /dev/null
+++ b/src/java/net/sf/antcontrib/perf/StopWatch.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.perf;
+
+/**
+ * A stopwatch, useful for 'quick and dirty' performance testing. Typical usage:
+ * <pre>
+ * StopWatch sw = new StopWatch(); // automatically starts
+ * // do something here...
+ * sw.stop();
+ * System.out.println(sw.toString()); // print the total
+ * sw.start(); // restart the stopwatch
+ * // do some more things...
+ * sw.stop();
+ * System.out.println(sw.format(sw.elapsed()); // print the time since the last start
+ * System.out.println(sw.toString()); // print the cumulative total
+ * </pre>
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author Dale Anson
+ * @version $Revision: 1.4 $
+ */
+public class StopWatch {
+
+ /** an identifying name for this stopwatch */
+ private String name = "";
+
+ /** storage for start time */
+ private long startTime = 0;
+
+ /** storage for stop time */
+ private long stopTime = 0;
+
+ /** cumulative elapsed time */
+ private long totalTime = 0;
+
+ /** is the stopwatch running? */
+ private boolean running = false;
+
+ /**
+ * Starts the stopwatch.
+ */
+ public StopWatch() {
+ this( "" );
+ }
+
+ /**
+ * Starts the stopwatch.
+ * @param name an identifying name for this StopWatch
+ */
+ public StopWatch( String name ) {
+ this.name = name;
+ start();
+ }
+
+ /**
+ * Starts/restarts the stopwatch. <code>stop</code> must be called prior
+ * to restart.
+ *
+ * @return the start time, the long returned System.currentTimeMillis().
+ */
+ public long start() {
+ if ( !running )
+ startTime = System.currentTimeMillis();
+ running = true;
+ return startTime;
+ }
+
+ /**
+ * Stops the stopwatch.
+ *
+ * @return the stop time, the long returned System.currentTimeMillis().
+ */
+ public long stop() {
+ stopTime = System.currentTimeMillis();
+ if ( running ) {
+ totalTime += stopTime - startTime;
+ }
+ startTime = stopTime;
+ running = false;
+ return stopTime;
+ }
+
+ /**
+ * Total cumulative elapsed time.
+ *
+ * @return the total time
+ */
+ public long total() {
+ stop();
+ long rtn = totalTime;
+ totalTime = 0;
+ return rtn;
+ }
+
+ /**
+ * Elapsed time, difference between the last start time and now.
+ *
+ * @return the elapsed time
+ */
+ public long elapsed() {
+ return System.currentTimeMillis() - startTime;
+ }
+
+ /**
+ * @return the name of this StopWatch
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Formats the given time into decimal seconds.
+ * @return the time formatted as mm:ss.ddd
+ */
+ public String format( long ms ) {
+ String total = String.valueOf( ms );
+ String frontpad = "000";
+ int pad_length = 3 - total.length();
+ if ( pad_length >= 0 )
+ total = "0." + frontpad.substring( 0, pad_length ) + total;
+ else {
+ String dec = total.substring( total.length() - 3 );
+ total = "";
+ int min = 0, sec = 0;
+ min = ( int ) ( ms / 60000 );
+ sec = min > 0 ? ( int ) ( ( ms - ( min * 60000 ) ) / 1000 ) : ( int ) ( ms / 1000 );
+ if ( min > 0 ) {
+ total = String.valueOf( min ) + ":" + ( sec < 10 ? "0" : "" ) + String.valueOf( sec ) + "." + dec;
+ }
+ else {
+ total = String.valueOf( sec ) + "." + dec;
+ }
+ }
+ return total + " sec";
+ }
+
+ /**
+ * Returns the total elapsed time of the stopwatch formatted in decimal seconds.
+ * @return [name: mm:ss.ddd]
+ */
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append( "[" );
+ if ( name != null )
+ sb.append( name ).append( ": " );
+ sb.append( format( totalTime ) );
+ sb.append( "]" );
+ return sb.toString();
+ }
+
+ public static void main ( String[] args ) {
+ StopWatch sw = new StopWatch( "test" );
+
+ // test the formatter
+ System.out.println( sw.format( 1 ) );
+ System.out.println( sw.format( 10 ) );
+ System.out.println( sw.format( 100 ) );
+ System.out.println( sw.format( 1000 ) );
+ System.out.println( sw.format( 100000 ) );
+ System.out.println( sw.format( 1000000 ) );
+
+ // test the stopwatch
+ try {
+ System.out.println( "StopWatch: " + sw.getName() );
+ Thread.currentThread().sleep( 2000 );
+ sw.stop();
+ System.out.println( sw.toString() );
+ sw.start();
+ Thread.currentThread().sleep( 2000 );
+ sw.stop();
+ System.out.println( "elapsed: " + sw.format( sw.elapsed() ) );
+ System.out.println( "total: " + sw.format( sw.total() ) );
+ }
+ catch ( Exception e ) {
+ e.printStackTrace();
+ }
+ }
+}
+
diff --git a/src/java/net/sf/antcontrib/perf/StopWatchTask.java b/src/java/net/sf/antcontrib/perf/StopWatchTask.java
new file mode 100644
index 0000000..5de4163
--- /dev/null
+++ b/src/java/net/sf/antcontrib/perf/StopWatchTask.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.perf;
+
+import java.util.Hashtable;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+/**
+ * Assists in timing tasks and/or targets.
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ * @author Dale Anson, [email protected]
+ * @version $Revision: 1.5 $
+ */
+public class StopWatchTask extends Task {
+
+ // storage for stopwatch name
+ private String name = null;
+
+ // storage for action
+ private String action = null;
+
+ // storage for watches
+ private static Hashtable watches = null;
+
+ // action definitions
+ private static final String STOP = "stop";
+ private static final String START = "start";
+ private static final String ELAPSED = "elapsed";
+ private static final String TOTAL = "total";
+
+
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+ public void setAction( String action ) {
+ action = action.toLowerCase();
+ if ( action.equals( STOP ) ||
+ action.equals( START ) ||
+ action.equals( ELAPSED ) ||
+ action.equals( TOTAL ) ) {
+ this.action = action;
+ }
+ else {
+ throw new BuildException( "invalid action: " + action );
+ }
+ }
+
+ public void execute() {
+ if ( name == null )
+ throw new BuildException( "name is null" );
+ if ( action == null )
+ action = START;
+ if ( watches == null )
+ watches = new Hashtable();
+ StopWatch sw = ( StopWatch ) watches.get( name );
+ if ( sw == null && action.equals( START ) ) {
+ sw = new StopWatch( name );
+ watches.put( name, sw );
+ return ;
+ }
+ if ( sw == null )
+ return ;
+ if ( action.equals( START) ) {
+ sw.start();
+ return;
+ }
+ if ( action.equals( STOP ) ) {
+ sw.stop();
+ return ;
+ }
+ if ( action.equals( TOTAL ) ) {
+ String time = sw.format( sw.total() );
+ log( "[" + name + ": " + time + "]" );
+ getProject().setProperty(name, time);
+ return ;
+ }
+ if ( action.equals( ELAPSED ) ) {
+ String time = sw.format( sw.elapsed() );
+ log( "[" + name + ": " + time + "]" );
+ getProject().setProperty(name, time);
+ return ;
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/platform/OsFamily.java b/src/java/net/sf/antcontrib/platform/OsFamily.java
new file mode 100644
index 0000000..851969b
--- /dev/null
+++ b/src/java/net/sf/antcontrib/platform/OsFamily.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.platform;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+
+/***
+ * Task definition for the <code>OsFamily</code> task.
+ * This task sets the property indicated in the "property"
+ * attribute with the string representing the operating
+ * system family. Possible values include "unix", "dos", "mac"
+ * and "windows".
+ *
+ * <pre>
+ *
+ * Task Declaration:
+ *
+ * <code>
+ * &lt;taskdef name="osfamily" classname="net.sf.antcontrib.platform.OsFamily" /&gt;
+ * </code>
+ *
+ * Usage:
+ * <code>
+ * &lt;osfamily property="propname" /&gt;
+ * </code>
+ *
+ * Attributes:
+ * property --> The name of the property to set with the OS family name
+ *
+ * </pre>
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ */
+public class OsFamily extends Task
+{
+ private String property;
+
+ public OsFamily()
+ {
+ }
+
+ public void setProperty(String property)
+ {
+ this.property = property;
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ if (property == null)
+ throw new BuildException("The attribute 'property' is required " +
+ "for the OsFamily task.");
+
+ String familyStr = Platform.getOsFamilyName();
+ if (familyStr != null)
+ getProject().setProperty(property, familyStr);
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/platform/Platform.java b/src/java/net/sf/antcontrib/platform/Platform.java
new file mode 100644
index 0000000..23e32f6
--- /dev/null
+++ b/src/java/net/sf/antcontrib/platform/Platform.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.platform;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.apache.tools.ant.taskdefs.Execute;
+
+/***
+ *
+ * </pre>
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ */
+public class Platform
+{
+ public static final int FAMILY_NONE = 0;
+ public static final int FAMILY_UNIX = 1;
+ public static final int FAMILY_WINDOWS = 2;
+ public static final int FAMILY_OS2 = 3;
+ public static final int FAMILY_ZOS = 4;
+ public static final int FAMILY_OS400 = 5;
+ public static final int FAMILY_DOS = 6;
+ public static final int FAMILY_MAC = 7;
+ public static final int FAMILY_MACOSX = 8;
+ public static final int FAMILY_TANDEM = 9;
+ public static final int FAMILY_OPENVMS = 10;
+
+ public static final String FAMILY_NAME_UNIX = "unix";
+ public static final String FAMILY_NAME_WINDOWS = "windows";
+ public static final String FAMILY_NAME_OS2 = "os/2";
+ public static final String FAMILY_NAME_ZOS = "z/os";
+ public static final String FAMILY_NAME_OS400 = "os/400";
+ public static final String FAMILY_NAME_DOS = "dos";
+ public static final String FAMILY_NAME_MAC = "mac";
+ public static final String FAMILY_NAME_TANDEM = "tandem";
+ public static final String FAMILY_NAME_OPENVMS = "openvms";
+
+ private static final Hashtable familyNames;
+
+ static
+ {
+ familyNames = new Hashtable();
+ familyNames.put(new Integer(FAMILY_WINDOWS), FAMILY_NAME_WINDOWS);
+ familyNames.put(new Integer(FAMILY_OS2), FAMILY_NAME_OS2);
+ familyNames.put(new Integer(FAMILY_ZOS), FAMILY_NAME_ZOS);
+ familyNames.put(new Integer(FAMILY_OS400), FAMILY_NAME_OS400);
+ familyNames.put(new Integer(FAMILY_DOS), FAMILY_NAME_DOS);
+ familyNames.put(new Integer(FAMILY_MAC), FAMILY_NAME_MAC);
+ familyNames.put(new Integer(FAMILY_MACOSX), FAMILY_NAME_UNIX);
+ familyNames.put(new Integer(FAMILY_TANDEM), FAMILY_NAME_TANDEM);
+ familyNames.put(new Integer(FAMILY_UNIX), FAMILY_NAME_UNIX);
+ familyNames.put(new Integer(FAMILY_OPENVMS), FAMILY_NAME_OPENVMS);
+ }
+
+ public static final int getOsFamily()
+ {
+ String osName = System.getProperty("os.name").toLowerCase();
+ String pathSep = System.getProperty("path.separator");
+ int family = FAMILY_NONE;
+
+ if (osName.indexOf("windows") != -1)
+ {
+ family = FAMILY_WINDOWS;
+ }
+ else if (osName.indexOf("os/2") != -1)
+ {
+ family = FAMILY_OS2;
+ }
+ else if (osName.indexOf("z/os") != -1
+ || osName.indexOf("os/390") != -1)
+ {
+ family = FAMILY_ZOS;
+ }
+ else if (osName.indexOf("os/400") != -1)
+ {
+ family = FAMILY_OS400;
+ }
+ else if (pathSep.equals(";"))
+ {
+ family = FAMILY_DOS;
+ }
+ else if (osName.indexOf("mac") != -1)
+ {
+ if (osName.endsWith("x"))
+ family = FAMILY_UNIX; // MACOSX
+ else
+ family = FAMILY_MAC;
+ }
+ else if (osName.indexOf("nonstop_kernel") != -1)
+ {
+ family = FAMILY_TANDEM;
+ }
+ else if (osName.indexOf("openvms") != -1)
+ {
+ family = FAMILY_OPENVMS;
+ }
+ else if (pathSep.equals(":"))
+ {
+ family = FAMILY_UNIX;
+ }
+
+ return family;
+ }
+
+ public static final String getOsFamilyName()
+ {
+ int family = getOsFamily();
+ return (String)(familyNames.get(new Integer(family)));
+ }
+
+ public static final Properties getEnv()
+ {
+ Properties env = new Properties();
+ Vector osEnv = Execute.getProcEnvironment();
+ for (Enumeration e = osEnv.elements(); e.hasMoreElements();) {
+ String entry = (String) e.nextElement();
+ int pos = entry.indexOf('=');
+ if (pos != -1) {
+ env.setProperty(entry.substring(0, pos),
+ entry.substring(pos + 1));
+ }
+ }
+ return env;
+ }
+
+ public static final String getDefaultShell()
+ {
+ String shell = getEnv().getProperty("SHELL");
+
+ if (shell == null)
+ {
+ int family = getOsFamily();
+ switch (family)
+ {
+ case FAMILY_DOS:
+ case FAMILY_WINDOWS:
+ {
+ shell = "CMD.EXE";
+ break;
+ }
+
+ default:
+ {
+ shell = "bash";
+ break;
+ }
+ }
+ }
+ return shell;
+ }
+
+ public static final String getDefaultScriptSuffix()
+ {
+ int family = getOsFamily();
+ String suffix = null;
+
+ switch (family)
+ {
+ case FAMILY_DOS:
+ case FAMILY_WINDOWS:
+ {
+ suffix = ".bat";
+ break;
+ }
+
+ default:
+ {
+ suffix = null;
+ break;
+ }
+ }
+
+ return suffix;
+ }
+
+
+ public static final String[] getDefaultShellArguments()
+ {
+ int family = getOsFamily();
+ String args[] = null;
+
+ switch (family)
+ {
+ case FAMILY_DOS:
+ case FAMILY_WINDOWS:
+ {
+ args = new String[] { "/c" , "call" };
+ break;
+ }
+
+ default:
+ {
+ args = new String[0];
+ break;
+ }
+ }
+
+ return args;
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/platform/ShellScriptTask.java b/src/java/net/sf/antcontrib/platform/ShellScriptTask.java
new file mode 100644
index 0000000..3b34d8f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/platform/ShellScriptTask.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.platform;
+
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.taskdefs.ExecTask;
+import org.apache.tools.ant.types.Commandline;
+import org.apache.tools.ant.util.FileUtils;
+
+/**
+ * A generic front-end for passing "shell lines" to any application which can
+ * accept a filename containing script input (bash, perl, csh, tcsh, etc.).
+ * see antcontrib doc for useage
+ *
+ * @author stephan beal
+ *@author peter reilly
+ */
+
+public class ShellScriptTask extends ExecTask {
+
+ private StringBuffer script = new StringBuffer();
+ private String shell = null;
+ private File tmpFile;
+ private String tmpSuffix = null;
+
+ /**
+ * Adds s to the lines of script code.
+ */
+ public void addText(String s) {
+ script.append(getProject().replaceProperties(s));
+ }
+
+ /**
+ * Sets script code to s.
+ */
+ public void setInputString(String s) {
+ script.append(s);
+ }
+
+ /**
+ * Sets the shell used to run the script.
+ * @param shell the shell to use (bash is default)
+ */
+ public void setShell(String shell) {
+ this.shell = shell;
+ }
+
+ /**
+ * Sets the shell used to run the script.
+ * @param shell the shell to use (bash is default)
+ */
+ public void setExecutable(String shell) {
+ this.shell = shell;
+ }
+
+ /**
+ * Disallow the command attribute of parent class ExecTask.
+ * ant.attribute ignore="true"
+ * @param notUsed not used
+ * @throws BuildException if called
+ */
+ public void setCommand(Commandline notUsed) {
+ throw new BuildException("Attribute command is not supported");
+ }
+
+
+ /**
+ * Sets the suffix for the tmp file used to
+ * contain the script.
+ * This is useful for cmd.exe as one can
+ * use cmd /c call x.bat
+ * @param tmpSuffix the suffix to use
+ */
+
+ public void setTmpSuffix(String tmpSuffix) {
+ this.tmpSuffix = tmpSuffix;
+ }
+
+ /**
+ * execute the task
+ */
+ public void execute() throws BuildException {
+ // Remove per peter's comments. Makes sense.
+ /*
+ if (shell == null)
+ {
+ // Get the default shell
+ shell = Platform.getDefaultShell();
+
+ // Get the default shell arguments
+ String args[] = Platform.getDefaultShellArguments();
+ for (int i=args.length-1;i>=0;i--)
+ this.cmdl.createArgument(true).setValue(args[i]);
+
+ // Get the default script suffix
+ if (tmpSuffix == null)
+ tmpSuffix = Platform.getDefaultScriptSuffix();
+
+ }
+ */
+ if (shell == null)
+ throw new BuildException("You must specify a shell to run.");
+
+ try {
+ /* // The following may be used when ant 1.6 is used.
+ if (tmpSuffix == null)
+ super.setInputString(script.toString());
+ else
+ */
+ {
+ writeScript();
+ super.createArg().setValue(tmpFile.getAbsolutePath());
+ }
+ super.setExecutable(shell);
+ super.execute();
+ }
+ finally {
+ if (tmpFile != null) {
+ if (! tmpFile.delete()) {
+ log("Non-fatal error: could not delete temporary file " +
+ tmpFile.getAbsolutePath());
+ }
+ }
+ }
+ }
+
+ /**
+ * Writes the script lines to a temp file.
+ */
+ protected void writeScript() throws BuildException {
+ FileOutputStream os = null;
+ try {
+ FileUtils fileUtils = FileUtils.newFileUtils();
+ // NB: use File.io.createTempFile whenever jdk 1.2 is allowed
+ tmpFile = fileUtils.createTempFile("script", tmpSuffix, null);
+ os = new java.io.FileOutputStream(tmpFile);
+ String string = script.toString();
+ os.write(string.getBytes(), 0, string.length());
+ os.close();
+ }
+ catch (Exception e) {
+ throw new BuildException(e);
+ }
+ finally {
+ try {os.close();} catch (Throwable t) {}
+ }
+ }
+
+}
+
diff --git a/src/java/net/sf/antcontrib/process/ForgetTask.java b/src/java/net/sf/antcontrib/process/ForgetTask.java
new file mode 100644
index 0000000..69990bd
--- /dev/null
+++ b/src/java/net/sf/antcontrib/process/ForgetTask.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.process;
+
+import org.apache.tools.ant.taskdefs.Sequential;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class ForgetTask
+ extends Sequential
+ implements Runnable
+{
+ private boolean daemon = true;
+
+ public ForgetTask()
+ {
+ super();
+ }
+
+
+ public void setDaemon(boolean daemon)
+ {
+ this.daemon = daemon;
+ }
+
+
+ public void execute()
+ {
+ Thread t = new Thread(this);
+ t.setDaemon(daemon);
+ t.start();
+ }
+
+ public void run()
+ {
+ super.execute();
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/process/Limit.java b/src/java/net/sf/antcontrib/process/Limit.java
new file mode 100644
index 0000000..b9cd7df
--- /dev/null
+++ b/src/java/net/sf/antcontrib/process/Limit.java
@@ -0,0 +1,402 @@
+
+/*
+* Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package net.sf.antcontrib.process;
+
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.TaskContainer;
+import org.apache.tools.ant.types.EnumeratedAttribute;
+
+
+/**
+ * Limits the amount of time that a task or set of tasks can run. This is useful
+ * for tasks that may "hang" or otherwise not complete in a timely fashion. This
+ * task is done when either the maxwait time has expired or all nested tasks are
+ * complete, whichever is first.
+ *
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author Dale Anson
+ * @author Robert D. Rice
+ * @version $Revision: 1.6 $
+ * @since Ant 1.5
+ */
+public class Limit extends Task implements TaskContainer {
+
+
+ // storage for nested tasks
+ private Vector tasks = new Vector();
+
+
+ // time units, default value is 3 minutes.
+ private long maxwait = 180;
+ protected TimeUnit unit = TimeUnit.SECOND_UNIT;
+
+ // property to set if time limit is reached
+ private String timeoutProperty = null;
+ private String timeoutValue = "true";
+
+
+ // storage for task currently executing
+ private Task currentTask = null;
+
+
+ // used to control thread stoppage
+ private Thread taskRunner = null;
+
+
+ // should the build fail if the time limit has expired? Default is no.
+ private boolean failOnError = false;
+
+
+ private Exception exception = null;
+
+
+
+
+ /**
+ * Add a task to wait on.
+ *
+ * @param task A task to execute
+ * @exception BuildException won't happen
+ */
+ public void addTask( Task task ) throws BuildException {
+ tasks.addElement( task );
+ }
+
+
+
+
+ /**
+ * How long to wait for all nested tasks to complete, in units.
+ * Default is to wait 3 minutes.
+ *
+ * @param wait time to wait, set to 0 to wait forever.
+ */
+ public void setMaxwait( int wait ) {
+ maxwait = wait;
+ }
+
+ /**
+ * Sets the unit for the max wait. Default is minutes.
+
+ * @param unit valid values are "millisecond", "second", "minute", "hour", "day", and "week".
+
+ */
+ public void setUnit( String unit ) {
+ if ( unit == null )
+ return ;
+ if ( unit.equals( TimeUnit.SECOND ) ) {
+ setMaxWaitUnit( TimeUnit.SECOND_UNIT );
+ return ;
+ }
+ if ( unit.equals( TimeUnit.MILLISECOND ) ) {
+ setMaxWaitUnit( TimeUnit.MILLISECOND_UNIT );
+ return ;
+ }
+ if ( unit.equals( TimeUnit.MINUTE ) ) {
+ setMaxWaitUnit( TimeUnit.MINUTE_UNIT );
+ return ;
+ }
+ if ( unit.equals( TimeUnit.HOUR ) ) {
+ setMaxWaitUnit( TimeUnit.HOUR_UNIT );
+ return ;
+ }
+ if ( unit.equals( TimeUnit.DAY ) ) {
+ setMaxWaitUnit( TimeUnit.DAY_UNIT );
+ return ;
+ }
+ if ( unit.equals( TimeUnit.WEEK ) ) {
+ setMaxWaitUnit( TimeUnit.WEEK_UNIT );
+ return ;
+ }
+
+ }
+
+ /**
+ * Set a millisecond wait value.
+ * @param value the number of milliseconds to wait.
+ */
+ public void setMilliseconds( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.MILLISECOND_UNIT );
+ }
+
+ /**
+ * Set a second wait value.
+ * @param value the number of seconds to wait.
+ */
+ public void setSeconds( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.SECOND_UNIT );
+ }
+
+ /**
+ * Set a minute wait value.
+ * @param value the number of milliseconds to wait.
+ */
+ public void setMinutes( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.MINUTE_UNIT );
+ }
+
+ /**
+ * Set an hours wait value.
+ * @param value the number of hours to wait.
+ */
+ public void setHours( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.HOUR_UNIT );
+ }
+
+ /**
+ * Set a day wait value.
+ * @param value the number of days to wait.
+ */
+ public void setDays( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.DAY_UNIT );
+ }
+
+ /**
+ * Set a week wait value.
+ * @param value the number of weeks to wait.
+ */
+ public void setWeeks( int value ) {
+ setMaxwait( value );
+ setMaxWaitUnit( TimeUnit.WEEK_UNIT );
+ }
+
+ /**
+ * Set the max wait time unit, default is minutes.
+ */
+ public void setMaxWaitUnit( TimeUnit unit ) {
+ this.unit = unit;
+ }
+
+
+ /**
+ * Determines whether the build should fail if the time limit has
+ * expired on this task.
+ * Default is no.
+ *
+ * @param fail if true, fail the build if the time limit has been reached.
+ */
+ public void setFailonerror( boolean fail ) {
+ failOnError = fail;
+ }
+
+
+ /**
+ * Name the property to set after a timeout.
+ *
+ * @param p of property to set if the time limit has been reached.
+ */
+ public void setProperty( String p ) {
+ timeoutProperty = p;
+ }
+
+
+ /**
+ * The value for the property to set after a timeout, defaults to true.
+ *
+ * @param v for the property to set if the time limit has been reached.
+ */
+ public void setValue( String v ) {
+ timeoutValue = v;
+ }
+
+
+ /**
+ * Execute all nested tasks, but stopping execution of nested tasks after
+ * maxwait or when all tasks are done, whichever is first.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ public void execute() throws BuildException {
+ try {
+ // start executing nested tasks
+ final Thread runner =
+ new Thread() {
+ public void run() {
+ Enumeration e = tasks.elements();
+ while ( e.hasMoreElements() ) {
+ if ( taskRunner != this ) {
+ break;
+ }
+ currentTask = ( Task ) e.nextElement();
+ try {
+ currentTask.perform();
+ }
+ catch ( Exception ex ) {
+ if ( failOnError ) {
+ exception = ex;
+ return ;
+ }
+ else {
+ exception = ex;
+ }
+ }
+ }
+ }
+ };
+ taskRunner = runner;
+ runner.start();
+ runner.join( unit.toMillis( maxwait ) );
+
+
+ // stop executing the nested tasks
+ if ( runner.isAlive() ) {
+ taskRunner = null;
+ runner.interrupt();
+ int index = tasks.indexOf( currentTask );
+ StringBuffer not_ran = new StringBuffer();
+ for ( int i = index + 1; i < tasks.size(); i++ ) {
+ not_ran.append( '<' ).append( ( ( Task ) tasks.get( i ) ).getTaskName() ).append( '>' );
+ if ( i < tasks.size() - 1 ) {
+ not_ran.append( ", " );
+ }
+ }
+
+
+ // maybe set timeout property
+ if ( timeoutProperty != null ) {
+ getProject().setNewProperty( timeoutProperty, timeoutValue );
+ }
+
+
+ // create output message
+ StringBuffer msg = new StringBuffer();
+ msg.append( "Interrupted task <" )
+ .append( currentTask.getTaskName() )
+ .append( ">. Waited " )
+ .append( ( maxwait ) ).append( " " ).append( unit.getValue() )
+ .append( ", but this task did not complete." )
+ .append( ( not_ran.length() > 0 ?
+ " The following tasks did not execute: " + not_ran.toString() + "." :
+ "" ) );
+
+
+ // deal with it
+ if ( failOnError ) {
+ throw new BuildException( msg.toString() );
+ }
+ else {
+ log( msg.toString() );
+ }
+ }
+ else if ( failOnError && exception != null ) {
+ throw new BuildException( exception );
+ }
+ }
+ catch ( Exception e ) {
+ throw new BuildException( e );
+ }
+ }
+
+
+ /**
+ * The enumeration of units:
+ * millisecond, second, minute, hour, day, week
+ * Todo: we use timestamps in many places, why not factor this out
+ */
+ public static class TimeUnit extends EnumeratedAttribute {
+
+ public static final String MILLISECOND = "millisecond";
+ public static final String SECOND = "second";
+ public static final String MINUTE = "minute";
+ public static final String HOUR = "hour";
+ public static final String DAY = "day";
+ public static final String WEEK = "week";
+
+ /** static unit objects, for use as sensible defaults */
+ public static final TimeUnit MILLISECOND_UNIT =
+ new TimeUnit( MILLISECOND );
+ public static final TimeUnit SECOND_UNIT =
+ new TimeUnit( SECOND );
+ public static final TimeUnit MINUTE_UNIT =
+ new TimeUnit( MINUTE );
+ public static final TimeUnit HOUR_UNIT =
+ new TimeUnit( HOUR );
+ public static final TimeUnit DAY_UNIT =
+ new TimeUnit( DAY );
+ public static final TimeUnit WEEK_UNIT =
+ new TimeUnit( WEEK );
+
+
+ private static final String[] units = {
+ MILLISECOND, SECOND, MINUTE, HOUR, DAY, WEEK
+ };
+
+ private Hashtable timeTable = new Hashtable();
+
+ public TimeUnit() {
+ timeTable.put( MILLISECOND, new Long( 1L ) );
+ timeTable.put( SECOND, new Long( 1000L ) );
+ timeTable.put( MINUTE, new Long( 1000L * 60L ) );
+ timeTable.put( HOUR, new Long( 1000L * 60L * 60L ) );
+ timeTable.put( DAY, new Long( 1000L * 60L * 60L * 24L ) );
+ timeTable.put( WEEK, new Long( 1000L * 60L * 60L * 24L * 7L ) );
+ }
+
+ /**
+ * private constructor
+ * used for static construction of TimeUnit objects.
+ * @param value String representing the value.
+ */
+ private TimeUnit( String value ) {
+ this( );
+ setValueProgrammatically( value );
+ }
+
+ /**
+ * set the inner value programmatically.
+ * @param value to set
+ */
+ protected void setValueProgrammatically( String value ) {
+ this.value = value;
+ }
+
+ public long getMultiplier() {
+ String key = getValue().toLowerCase();
+ Long l = ( Long ) timeTable.get( key );
+ return l.longValue();
+ }
+
+ public String[] getValues() {
+ return units;
+ }
+
+ /**
+ * convert the time in the current unit, to millis
+ * @param numberOfUnits long expressed in the current objects units
+ * @return long representing the value in millis
+ */
+ public long toMillis( long numberOfUnits ) {
+ return numberOfUnits * getMultiplier( );
+ }
+ }
+}
+
+
+
diff --git a/src/java/net/sf/antcontrib/property/AbstractPropertySetterTask.java b/src/java/net/sf/antcontrib/property/AbstractPropertySetterTask.java
new file mode 100644
index 0000000..87b594f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/AbstractPropertySetterTask.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Property;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public abstract class AbstractPropertySetterTask
+ extends Task
+{
+ private boolean override;
+ private String property;
+
+ public AbstractPropertySetterTask()
+ {
+ super();
+ }
+
+
+ public void setOverride(boolean override)
+ {
+ this.override = override;
+ }
+
+
+ public void setProperty(String property)
+ {
+ this.property = property;
+ }
+
+ protected void validate()
+ {
+ if (property == null)
+ throw new BuildException("You must specify a property to set.");
+ }
+
+
+ protected final void setPropertyValue(String value)
+ {
+ if (value != null)
+ {
+ if (override)
+ {
+ if (getProject().getUserProperty(property) == null)
+ getProject().setProperty(property, value);
+ else
+ getProject().setUserProperty(property, value);
+ }
+ else
+ {
+ Property p = (Property)project.createTask("property");
+ p.setName(property);
+ p.setValue(value);
+ p.execute();
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/property/PathFilterTask.java b/src/java/net/sf/antcontrib/property/PathFilterTask.java
new file mode 100644
index 0000000..9547923
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/PathFilterTask.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.DirSet;
+import org.apache.tools.ant.types.FileList;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.selectors.OrSelector;
+
+public class PathFilterTask
+ extends Task {
+
+ private OrSelector select;
+ private Path path;
+ private String pathid;
+
+
+ public void setPathId(String pathid) {
+ this.pathid = pathid;
+ }
+
+ public OrSelector createSelect() {
+ select = new OrSelector();
+ return select;
+ }
+
+ public void addConfiguredFileSet(FileSet fileset) {
+ if (this.path == null) {
+ this.path = (Path)getProject().createDataType("path");
+ }
+ this.path.addFileset(fileset);
+ }
+
+ public void addConfiguredDirSet(DirSet dirset) {
+ if (this.path == null) {
+ this.path = (Path)getProject().createDataType("path");
+ }
+ this.path.addDirset(dirset);
+ }
+
+ public void addConfiguredFileList(FileList filelist) {
+ if (this.path == null) {
+ this.path = (Path)getProject().createDataType("path");
+ }
+ this.path.addFilelist(filelist);
+ }
+
+ public void addConfiguredPath(Path path) {
+ if (this.path == null) {
+ this.path = (Path)getProject().createDataType("path");
+ }
+ this.path.add(path);
+ }
+
+
+ public void execute() throws BuildException {
+ if (select == null) {
+ throw new BuildException("A <select> element must be specified.");
+ }
+
+ if (pathid == null) {
+ throw new BuildException("A 'pathid' attribute must be specified.");
+ }
+
+ Path selectedFiles = (Path)getProject().createDataType("path");
+
+ if (this.path != null) {
+ String files[] = this.path.list();
+ for (int i=0;i<files.length;i++) {
+ File file = new File(files[i]);
+ if (select.isSelected(file.getParentFile(),
+ file.getName(),
+ file)) {
+ selectedFiles.createPathElement().setLocation(file);
+ }
+ }
+
+ getProject().addReference(pathid, selectedFiles);
+ }
+ }
+
+
+
+}
diff --git a/src/java/net/sf/antcontrib/property/PathToFileSet.java b/src/java/net/sf/antcontrib/property/PathToFileSet.java
new file mode 100644
index 0000000..d1231af
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/PathToFileSet.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.FileUtils;
+
+public class PathToFileSet
+ extends Task
+{
+ private File dir;
+ private String name;
+ private String pathRefId;
+ private boolean ignoreNonRelative = false;
+
+ private static FileUtils fileUtils = FileUtils.newFileUtils();
+
+ public void setDir(File dir) {
+ this.dir = dir;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setPathRefId(String pathRefId) {
+ this.pathRefId = pathRefId;
+ }
+
+ public void setIgnoreNonRelative(boolean ignoreNonRelative) {
+ this.ignoreNonRelative = ignoreNonRelative;
+ }
+
+ public void execute() {
+ if (dir == null)
+ throw new BuildException("missing dir");
+ if (name == null)
+ throw new BuildException("missing name");
+ if (pathRefId == null)
+ throw new BuildException("missing pathrefid");
+
+ if (! dir.isDirectory())
+ throw new BuildException(
+ dir.toString() + " is not a directory");
+
+ Object path = getProject().getReference(pathRefId);
+ if (path == null)
+ throw new BuildException("Unknown reference " + pathRefId);
+ if (! (path instanceof Path))
+ throw new BuildException(pathRefId + " is not a path");
+
+
+ String[] sources = ((Path) path).list();
+
+ FileSet fileSet = new FileSet();
+ fileSet.setProject(getProject());
+ fileSet.setDir(dir);
+ String dirNormal =
+ fileUtils.normalize(dir.getAbsolutePath()).getAbsolutePath();
+ if (! dirNormal.endsWith(File.separator)) {
+ dirNormal += File.separator;
+ }
+
+
+ boolean atLeastOne = false;
+ for (int i = 0; i < sources.length; ++i) {
+ File sourceFile = new File(sources[i]);
+ if (! sourceFile.exists())
+ continue;
+ String relativeName = getRelativeName(dirNormal, sourceFile);
+ if (relativeName == null && !ignoreNonRelative) {
+ throw new BuildException(
+ sources[i] + " is not relative to " + dir.getAbsolutePath());
+ }
+ if (relativeName == null)
+ continue;
+ fileSet.createInclude().setName(relativeName);
+ atLeastOne = true;
+ }
+
+ if (! atLeastOne) {
+ // need to make an empty fileset
+ fileSet.createInclude().setName("a:b:c:d//THis si &&& not a file !!! ");
+ }
+ getProject().addReference(name, fileSet);
+ }
+
+ private String getRelativeName(String dirNormal, File file) {
+ String fileNormal =
+ fileUtils.normalize(file.getAbsolutePath()).getAbsolutePath();
+ if (! fileNormal.startsWith(dirNormal))
+ return null;
+ return fileNormal.substring(dirNormal.length());
+ }
+}
+
diff --git a/src/java/net/sf/antcontrib/property/PropertyCopy.java b/src/java/net/sf/antcontrib/property/PropertyCopy.java
new file mode 100644
index 0000000..558c4ac
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/PropertyCopy.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import org.apache.tools.ant.BuildException;
+
+/***
+ * Task definition for the propertycopy task, which copies the value of a
+ * named property to another property. This is useful when you need to
+ * plug in the value of another property in order to get a property name
+ * and then want to get the value of that property name.
+ *
+ * <pre>
+ * Usage:
+ *
+ * Task declaration in the project:
+ * <code>
+ * &lt;taskdef name="propertycopy" classname="net.sf.antcontrib.property.PropertyCopy" /&gt;
+ * </code>
+ *
+ * Call Syntax:
+ * <code>
+ * &lt;propertycopy name="propname" from="copyfrom" (silent="true|false")? /&gt;
+ * </code>
+ *
+ * Attributes:
+ * name --&gt; The name of the property you wish to set with the value
+ * from --&gt; The name of the property you wish to copy the value from
+ * silent --&gt; Do you want to suppress the error if the "from" property
+ * does not exist, and just not set the property "name". Default
+ * is false.
+ *
+ * Example:
+ * &lt;property name="org" value="MyOrg" /&gt;
+ * &lt;property name="org.MyOrg.DisplayName" value="My Organiziation" /&gt;
+ * &lt;propertycopy name="displayName" from="org.${org}.DisplayName" /&gt;
+ * &lt;echo message="${displayName}" /&gt;
+ * </pre>
+ *
+ * @author <a href="mailto:[email protected]">Matthew Inger</a>
+ */
+public class PropertyCopy
+ extends AbstractPropertySetterTask
+{
+ private String from;
+ private boolean silent;
+
+ /***
+ * Default Constructor
+ */
+ public PropertyCopy()
+ {
+ super();
+ this.from = null;
+ this.silent = false;
+ }
+
+ public void setName(String name)
+ {
+ setProperty(name);
+ }
+
+ public void setFrom(String from)
+ {
+ this.from = from;
+ }
+
+ public void setSilent(boolean silent)
+ {
+ this.silent = silent;
+ }
+
+ protected void validate()
+ {
+ super.validate();
+ if (from == null)
+ throw new BuildException("Missing the 'from' attribute.");
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ validate();
+
+ String value = getProject().getProperty(from);
+
+ if (value == null && ! silent)
+ throw new BuildException("Property '" + from + "' is not defined.");
+
+ if (value != null)
+ setPropertyValue(value);
+ }
+
+}
+
+
diff --git a/src/java/net/sf/antcontrib/property/PropertySelector.java b/src/java/net/sf/antcontrib/property/PropertySelector.java
new file mode 100644
index 0000000..23328c4
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/PropertySelector.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.RegularExpression;
+import org.apache.tools.ant.util.regexp.Regexp;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class PropertySelector
+ extends AbstractPropertySetterTask
+{
+ private RegularExpression match;
+ private String select = "\\0";
+ private char delim = ',';
+ private boolean caseSensitive = true;
+ private boolean distinct = false;
+
+
+ public PropertySelector()
+ {
+ super();
+ }
+
+
+ public void setMatch(String match)
+ {
+ this.match = new RegularExpression();
+ this.match.setPattern(match);
+ }
+
+
+ public void setSelect(String select)
+ {
+ this.select = select;
+ }
+
+
+ public void setCaseSensitive(boolean caseSensitive)
+ {
+ this.caseSensitive = caseSensitive;
+ }
+
+
+ public void setDelimiter(char delim)
+ {
+ this.delim = delim;
+ }
+
+
+ public void setDistinct(boolean distinct)
+ {
+ this.distinct = distinct;
+ }
+
+
+ protected void validate()
+ {
+ super.validate();
+ if (match == null)
+ throw new BuildException("No match expression specified.");
+ }
+
+
+ public void execute()
+ throws BuildException
+ {
+ validate();
+
+ int options = 0;
+ if (!caseSensitive)
+ options |= Regexp.MATCH_CASE_INSENSITIVE;
+
+ Regexp regex = match.getRegexp(project);
+ Hashtable props = project.getProperties();
+ Enumeration e = props.keys();
+ StringBuffer buf = new StringBuffer();
+ int cnt = 0;
+
+ Vector used = new Vector();
+
+ while (e.hasMoreElements())
+ {
+ String key = (String) (e.nextElement());
+ if (regex.matches(key, options))
+ {
+ String output = select;
+ Vector groups = regex.getGroups(key, options);
+ int sz = groups.size();
+ for (int i = 0; i < sz; i++)
+ {
+ String s = (String) (groups.elementAt(i));
+
+ RegularExpression result = null;
+ result = new RegularExpression();
+ result.setPattern("\\\\" + i);
+ Regexp sregex = result.getRegexp(project);
+ output = sregex.substitute(output, s, Regexp.MATCH_DEFAULT);
+ }
+
+ if (!(distinct && used.contains(output)))
+ {
+ used.addElement(output);
+ if (cnt != 0) buf.append(delim);
+ buf.append(output);
+ cnt++;
+ }
+ }
+ }
+
+ if (buf.length() > 0)
+ setPropertyValue(buf.toString());
+ }
+}
diff --git a/src/java/net/sf/antcontrib/property/RegexTask.java b/src/java/net/sf/antcontrib/property/RegexTask.java
new file mode 100644
index 0000000..433835f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/RegexTask.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.RegularExpression;
+import org.apache.tools.ant.types.Substitution;
+import org.apache.tools.ant.util.regexp.Regexp;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class RegexTask
+ extends AbstractPropertySetterTask
+{
+ private String input;
+
+ private RegularExpression regexp;
+ private String select;
+ private Substitution replace;
+ private String defaultValue;
+
+ private boolean caseSensitive = true;
+ private boolean global = true;
+
+ public RegexTask()
+ {
+ super();
+ }
+
+ public void setInput(String input)
+ {
+ this.input = input;
+ }
+
+ public void setDefaultValue(String defaultValue)
+ {
+ this.defaultValue = defaultValue;
+ }
+
+ public void setRegexp(String regex)
+ {
+ if (this.regexp != null)
+ throw new BuildException("Cannot specify more than one regular expression");
+
+ this.regexp = new RegularExpression();
+ this.regexp.setPattern(regex);
+ }
+
+
+ public RegularExpression createRegexp()
+ {
+ if (this.regexp != null)
+ throw new BuildException("Cannot specify more than one regular expression");
+ regexp = new RegularExpression();
+ return regexp;
+ }
+
+ public void setReplace(String replace)
+ {
+ if (this.replace != null)
+ throw new BuildException("Cannot specify more than one replace expression");
+ if (select != null)
+ throw new BuildException("You cannot specify both a select and replace expression");
+ this.replace = new Substitution();
+ this.replace.setExpression(replace);
+ }
+
+ public Substitution createReplace()
+ {
+ if (replace != null)
+ throw new BuildException("Cannot specify more than one replace expression");
+ if (select != null)
+ throw new BuildException("You cannot specify both a select and replace expression");
+ replace = new Substitution();
+ return replace;
+ }
+
+ public void setSelect(String select)
+ {
+ if (replace != null)
+ throw new BuildException("You cannot specify both a select and replace expression");
+ this.select = select;
+ }
+
+ public void setCaseSensitive(boolean caseSensitive)
+ {
+ this.caseSensitive = caseSensitive;
+ }
+
+ public void setGlobal(boolean global)
+ {
+ this.global = global;
+ }
+
+ protected String doReplace()
+ throws BuildException
+ {
+ if (replace == null)
+ throw new BuildException("No replace expression specified.");
+
+ int options = 0;
+ if (! caseSensitive)
+ options |= Regexp.MATCH_CASE_INSENSITIVE;
+ if (global)
+ options |= Regexp.REPLACE_ALL;
+
+ Regexp sregex = regexp.getRegexp(project);
+
+ String output = null;
+
+ if (sregex.matches(input, options)) {
+ String expression = replace.getExpression(project);
+ output = sregex.substitute(input,
+ expression,
+ options);
+ }
+
+ if (output == null)
+ output = defaultValue;
+
+ return output;
+ }
+
+ protected String doSelect()
+ throws BuildException
+ {
+ int options = 0;
+ if (! caseSensitive)
+ options |= Regexp.MATCH_CASE_INSENSITIVE;
+
+ Regexp sregex = regexp.getRegexp(project);
+
+ String output = select;
+ Vector groups = sregex.getGroups(input, options);
+
+ if (groups != null && groups.size() > 0)
+ {
+ output = RegexUtil.select(select, groups);
+ }
+ else
+ {
+ output = null;
+ }
+
+ if (output == null)
+ output = defaultValue;
+
+ return output;
+ }
+
+
+ protected void validate()
+ {
+ super.validate();
+ if (regexp == null)
+ throw new BuildException("No match expression specified.");
+ if (replace == null && select == null)
+ throw new BuildException("You must specify either a replace or select expression");
+ }
+
+ public void execute()
+ throws BuildException
+ {
+ validate();
+
+ String output = input;
+ if (replace != null)
+ output = doReplace();
+ else
+ output = doSelect();
+
+ if (output != null)
+ setPropertyValue(output);
+ }
+}
diff --git a/src/java/net/sf/antcontrib/property/RegexUtil.java b/src/java/net/sf/antcontrib/property/RegexUtil.java
new file mode 100644
index 0000000..0a8b350
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/RegexUtil.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.util.Enumeration;
+import java.util.Vector;
+
+/****************************************************************************
+ * Regular Expression utilities
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class RegexUtil
+{
+
+ /***
+ * An abritrary node in a select expression
+ */
+ private static interface SelectNode
+ {
+ /***
+ * Select the value based on the groups
+ * @param groups The groups found in the match
+ */
+ public String select(Vector groups);
+ }
+
+ /***
+ * A group node in a select expression
+ */
+ private static class GroupSelectNode
+ implements SelectNode
+ {
+ private int groupNumber;
+
+ public GroupSelectNode(int groupNumber)
+ {
+ this.groupNumber = groupNumber;
+ }
+
+ public String select(Vector groups)
+ {
+ if ( groupNumber < groups.size())
+ return (String)groups.elementAt(groupNumber);
+ else
+ return "\\" + groupNumber;
+ }
+
+ public String toString()
+ {
+ return "group: " + groupNumber;
+ }
+ }
+
+ /***
+ * An abritrary node in a select expression
+ */
+ private static class StringSelectNode
+ implements SelectNode
+ {
+ private String text;
+
+ public StringSelectNode(String text)
+ {
+ this.text = text;
+ }
+
+ public String select(Vector groups)
+ {
+ return text;
+ }
+
+ public String toString()
+ {
+ return "string: " + text;
+ }
+ }
+
+ /***
+ * Parses a select string into a List of SelectNode objects.
+ * These objects can then be merged with a group list to produce
+ * an output string (using the "select" method)
+ * @param input The select string
+ * @return a List of SelectNode objects
+ */
+ private static Vector parseSelectString(String input)
+ {
+ Vector nodes = new Vector();
+ StringBuffer buf = new StringBuffer();
+ char c[] = input.toCharArray();
+ for (int i=0;i<c.length;i++)
+ {
+ if (c[i] == '\\')
+ {
+ if (buf.length() > 0)
+ {
+ nodes.addElement(new StringSelectNode(buf.toString()));
+ buf.setLength(0);
+ }
+
+ while (i+1 < c.length && Character.isDigit(c[i+1]))
+ {
+ buf.append(c[i+1]);
+ i++;
+ }
+
+ int groupNum = Integer.parseInt(buf.toString());
+ buf.setLength(0);
+ nodes.addElement(new GroupSelectNode(groupNum));
+ }
+ else
+ {
+ buf.append(c[i]);
+ }
+ }
+
+
+ if (buf.length() > 0)
+ {
+ nodes.addElement(new StringSelectNode(buf.toString()));
+ buf.setLength(0);
+ }
+
+ return nodes;
+ }
+
+ /***
+ * Parse a select string, and merge it with a match groups
+ * vector to produce an output string. Each group placehold
+ * in the select string is replaced with the group at the
+ * corresponding index in the match groups vector
+ * @param select The select string
+ * @param groups The match groups
+ * @return The output string with the merged selection
+ */
+ public static String select(String select, Vector groups)
+ {
+ Vector nodes = parseSelectString(select);
+
+ StringBuffer buf = new StringBuffer();
+ Enumeration e = nodes.elements();
+ SelectNode node = null;
+ while (e.hasMoreElements())
+ {
+ node = (SelectNode)e.nextElement();
+ buf.append(node.select(groups));
+ }
+ return buf.toString();
+ }
+}
diff --git a/src/java/net/sf/antcontrib/property/SortList.java b/src/java/net/sf/antcontrib/property/SortList.java
new file mode 100644
index 0000000..f6e9440
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/SortList.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package net.sf.antcontrib.property;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.StringTokenizer;
+import java.util.Vector;
+import java.util.Locale;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.Reference;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class SortList
+ extends AbstractPropertySetterTask
+{
+ private String value;
+ private Reference ref;
+ private boolean casesensitive = true;
+ private boolean numeric = false;
+ private String delimiter = ",";
+ private File orderPropertyFile;
+ private String orderPropertyFilePrefix;
+
+ public SortList()
+ {
+ super();
+ }
+
+ public void setNumeric(boolean numeric)
+ {
+ this.numeric = numeric;
+ }
+
+ public void setValue(String value)
+ {
+ this.value = value;
+ }
+
+
+ public void setRefid(Reference ref)
+ {
+ this.ref = ref;
+ }
+
+
+ public void setCasesensitive(boolean casesenstive)
+ {
+ this.casesensitive = casesenstive;
+ }
+
+ public void setDelimiter(String delimiter)
+ {
+ this.delimiter = delimiter;
+ }
+
+
+ public void setOrderPropertyFile(File orderPropertyFile)
+ {
+ this.orderPropertyFile = orderPropertyFile;
+ }
+
+
+ public void setOrderPropertyFilePrefix(String orderPropertyFilePrefix)
+ {
+ this.orderPropertyFilePrefix = orderPropertyFilePrefix;
+ }
+
+
+ private static void mergeSort(String src[],
+ String dest[],
+ int low,
+ int high,
+ boolean caseSensitive,
+ boolean numeric) {
+ int length = high - low;
+
+ // Insertion sort on smallest arrays
+ if (length < 7) {
+ for (int i=low; i<high; i++)
+ for (int j=i; j>low &&
+ compare(dest[j-1],dest[j], caseSensitive, numeric)>0; j--)
+ swap(dest, j, j-1);
+ return;
+ }
+
+ // Recursively sort halves of dest into src
+ int mid = (low + high)/2;
+ mergeSort(dest, src, low, mid, caseSensitive, numeric);
+ mergeSort(dest, src, mid, high, caseSensitive, numeric);
+
+ // If list is already sorted, just copy from src to dest. This is an
+ // optimization that results in faster sorts for nearly ordered lists.
+ if (compare(src[mid-1], src[mid], caseSensitive, numeric) <= 0) {
+ System.arraycopy(src, low, dest, low, length);
+ return;
+ }
+
+ // Merge sorted halves (now in src) into dest
+ for(int i = low, p = low, q = mid; i < high; i++) {
+ if (q>=high || p<mid && compare(src[p], src[q], caseSensitive, numeric)<=0)
+ dest[i] = src[p++];
+ else
+ dest[i] = src[q++];
+ }
+ }
+
+ private static int compare(String s1,
+ String s2,
+ boolean casesensitive,
+ boolean numeric)
+ {
+ int res = 0;
+
+ if (numeric)
+ {
+ double d1 = new Double(s1).doubleValue();
+ double d2 = new Double(s2).doubleValue();
+ if (d1 < d2)
+ res = -1;
+ else if (d1 == d2)
+ res = 0;
+ else
+ res = 1;
+ }
+ else if (casesensitive)
+ {
+ res = s1.compareTo(s2);
+ }
+ else
+ {
+ Locale l = Locale.getDefault();
+ res = s1.toLowerCase(l).compareTo(s2.toLowerCase(l));
+ }
+
+ return res;
+ }
+
+ /**
+ * Swaps x[a] with x[b].
+ */
+ private static void swap(Object x[], int a, int b) {
+ Object t = x[a];
+ x[a] = x[b];
+ x[b] = t;
+ }
+
+
+ private Vector sortByOrderPropertyFile(Vector props)
+ throws IOException
+ {
+ FileReader fr = null;
+ Vector orderedProps = new Vector();
+
+ try
+ {
+ fr = new FileReader(orderPropertyFile);
+ BufferedReader br = new BufferedReader(fr);
+ String line = "";
+ String pname = "";
+ int pos = 0;
+ while ((line = br.readLine()) != null)
+ {
+ pos = line.indexOf('#');
+ if (pos != -1)
+ line = line.substring(0, pos).trim();
+
+ if (line.length() > 0)
+ {
+ pos = line.indexOf('=');
+ if (pos != -1)
+ pname = line.substring(0,pos).trim();
+ else
+ pname = line.trim();
+
+ String prefPname = pname;
+ if (orderPropertyFilePrefix != null)
+ prefPname = orderPropertyFilePrefix + "." + prefPname;
+
+ if (props.contains(prefPname) &&
+ ! orderedProps.contains(prefPname))
+ {
+ orderedProps.addElement(prefPname);
+ }
+ }
+ }
+
+ Enumeration e = props.elements();
+ while (e.hasMoreElements())
+ {
+ String prop = (String)(e.nextElement());
+ if (! orderedProps.contains(prop))
+ orderedProps.addElement(prop);
+ }
+
+ return orderedProps;
+ }
+ finally
+ {
+ try
+ {
+ if (fr != null)
+ fr.close();
+ }
+ catch (IOException e)
+ {
+ ; // gulp
+ }
+ }
+ }
+
+ protected void validate()
+ {
+ super.validate();
+ }
+
+ public void execute()
+ {
+ validate();
+
+ String val = value;
+ if (val == null && ref != null)
+ val = ref.getReferencedObject(project).toString();
+
+ if (val == null)
+ throw new BuildException("Either the 'Value' or 'Refid' attribute must be set.");
+
+ StringTokenizer st = new StringTokenizer(val, delimiter);
+ Vector vec = new Vector(st.countTokens());
+ while (st.hasMoreTokens())
+ vec.addElement(st.nextToken());
+
+
+ String propList[] = null;
+
+ if (orderPropertyFile != null)
+ {
+ try
+ {
+ Vector sorted = sortByOrderPropertyFile(vec);
+ propList = new String[sorted.size()];
+ sorted.copyInto(propList);
+ }
+ catch (IOException e)
+ {
+ throw new BuildException(e);
+ }
+ }
+ else
+ {
+ String s[] = (String[])(vec.toArray(new String[vec.size()]));
+ propList = new String[s.length];
+ System.arraycopy(s, 0, propList, 0, s.length);
+ mergeSort(s, propList, 0, s.length, casesensitive, numeric);
+ }
+
+ StringBuffer sb = new StringBuffer();
+ for (int i=0;i<propList.length;i++)
+ {
+ if (i != 0) sb.append(delimiter);
+ sb.append(propList[i]);
+ }
+
+ setPropertyValue(sb.toString());
+ }
+}
diff --git a/src/java/net/sf/antcontrib/property/URLEncodeTask.java b/src/java/net/sf/antcontrib/property/URLEncodeTask.java
new file mode 100644
index 0000000..cb11365
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/URLEncodeTask.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.io.File;
+import java.net.URLEncoder;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Reference;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class URLEncodeTask
+ extends AbstractPropertySetterTask
+{
+ private String value;
+ private Reference ref;
+
+ public void setName(String name)
+ {
+ setProperty(name);
+ }
+
+
+ public void setValue(String value)
+ {
+ this.value = URLEncoder.encode(value);
+ }
+
+ public String getValue(Project p)
+ {
+ String val = value;
+
+ if (ref != null)
+ val = ref.getReferencedObject(p).toString();
+
+ return val;
+ }
+
+ public void setLocation(File location) {
+ setValue(location.getAbsolutePath());
+ }
+
+ public void setRefid(Reference ref) {
+ this.ref = ref;
+ }
+
+ public String toString() {
+ return value == null ? "" : value;
+ }
+
+ protected void validate()
+ {
+ super.validate();
+ if (value == null && ref == null)
+ {
+ throw new BuildException("You must specify value, location or "
+ + "refid with the name attribute",
+ getLocation());
+ }
+ }
+
+ public void execute()
+ {
+ validate();
+ String val = getValue(getProject());
+ setPropertyValue(val);
+ }
+
+}
diff --git a/src/java/net/sf/antcontrib/property/Variable.java b/src/java/net/sf/antcontrib/property/Variable.java
new file mode 100644
index 0000000..013014c
--- /dev/null
+++ b/src/java/net/sf/antcontrib/property/Variable.java
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.Task;
+
+/**
+ * Similar to Property, but this property is mutable. In fact, much of the code
+ * in this class is copy and paste from Property. In general, the standard Ant
+ * property should be used, but occasionally it is useful to use a mutable
+ * property.
+ * <p>
+ * This used to be a nice little task that took advantage of what is probably
+ * a flaw in the Ant Project API -- setting a "user" property programatically
+ * causes the project to overwrite a previously set property. Now this task
+ * has become more violent and employs a technique known as "object rape" to
+ * directly access the Project's private property hashtable.
+ * <p>Developed for use with Antelope, migrated to ant-contrib Oct 2003.
+ *
+ * @author Dale Anson, [email protected]
+ * @since Ant 1.5
+ * @version $Revision: 1.6 $
+ */
+public class Variable extends Task {
+
+ // attribute storage
+ private String value = "";
+ private String name = null;
+ private File file = null;
+ private boolean remove = false;
+
+
+ /**
+ * Set the name of the property. Required unless 'file' is used.
+ *
+ * @param name the name of the property.
+ */
+ public void setName( String name ) {
+ this.name = name;
+ }
+
+
+ /**
+ * Set the value of the property. Optional, defaults to "".
+ *
+ * @param value the value of the property.
+ */
+ public void setValue( String value ) {
+ this.value = value;
+ }
+
+
+ /**
+ * Set the name of a file to read properties from. Optional.
+ *
+ * @param file the file to read properties from.
+ */
+ public void setFile( File file ) {
+ this.file = file;
+ }
+
+ /**
+ * Determines whether the property should be removed from the project.
+ * Default is false. Once removed, conditions that check for property
+ * existence will find this property does not exist.
+ *
+ * @param b set to true to remove the property from the project.
+ */
+ public void setUnset( boolean b ) {
+ remove = b;
+ }
+
+
+ /**
+ * Execute this task.
+ *
+ * @exception BuildException Description of the Exception
+ */
+ public void execute() throws BuildException {
+ if ( remove ) {
+ if ( name == null || name.equals( "" ) ) {
+ throw new BuildException( "The 'name' attribute is required with 'unset'." );
+ }
+ removeProperty( name );
+ return ;
+ }
+ if ( file == null ) {
+ // check for the required name attribute
+ if ( name == null || name.equals( "" ) ) {
+ throw new BuildException( "The 'name' attribute is required." );
+ }
+
+ // check for the required value attribute
+ if ( value == null ) {
+ value = "";
+ }
+
+ // adjust the property value if necessary -- is this necessary?
+ // Doesn't Ant do this automatically?
+ value = getProject().replaceProperties( value );
+
+ // set the property
+ forceProperty( name, value );
+ }
+ else {
+ if ( !file.exists() ) {
+ throw new BuildException( file.getAbsolutePath() + " does not exists." );
+ }
+ loadFile( file );
+ }
+ }
+
+ /**
+ * Remove a property from the project's property table and the userProperty table.
+ * Note that Ant 1.6 uses a helper for this.
+ */
+ private void removeProperty( String name ) {
+ Hashtable properties = null;
+ // Ant 1.5 stores properties in Project
+ try {
+ properties = ( Hashtable ) getValue( getProject(), "properties" );
+ if ( properties != null ) {
+ properties.remove( name );
+ }
+ }
+ catch ( Exception e ) {
+ // ignore, could be Ant 1.6
+ }
+ try {
+ properties = ( Hashtable ) getValue( getProject(), "userProperties" );
+ if ( properties != null ) {
+ properties.remove( name );
+ }
+ }
+ catch ( Exception e ) {
+ // ignore, could be Ant 1.6
+ }
+
+ // Ant 1.6 uses a PropertyHelper, can check for it by checking for a
+ // reference to "ant.PropertyHelper"
+ try {
+ Object property_helper = getProject().getReference( "ant.PropertyHelper" );
+ if ( property_helper != null ) {
+ try {
+ properties = ( Hashtable ) getValue( property_helper, "properties" );
+ if ( properties != null ) {
+ properties.remove( name );
+ }
+ }
+ catch ( Exception e ) {
+ // ignore
+ }
+ try {
+ properties = ( Hashtable ) getValue( property_helper, "userProperties" );
+ if ( properties != null ) {
+ properties.remove( name );
+ }
+ }
+ catch ( Exception e ) {
+ // ignore
+ }
+ }
+ }
+ catch ( Exception e ) {
+ // ignore, could be Ant 1.5
+ }
+ }
+
+ private void forceProperty( String name, String value ) {
+ try {
+ Hashtable properties = ( Hashtable ) getValue( getProject(), "properties" );
+ if ( properties == null ) {
+ getProject().setUserProperty( name, value );
+ }
+ else {
+ properties.put( name, value );
+ }
+ }
+ catch ( Exception e ) {
+ getProject().setUserProperty( name, value );
+ }
+ }
+
+
+ /**
+ * Object rape: fondle the private parts of an object without it's
+ * permission.
+ *
+ * @param thisClass The class to rape.
+ * @param fieldName The field to fondle
+ * @return The field value
+ * @exception NoSuchFieldException Darn, nothing to fondle.
+ */
+ private Field getField( Class thisClass, String fieldName ) throws NoSuchFieldException {
+ if ( thisClass == null ) {
+ throw new NoSuchFieldException( "Invalid field : " + fieldName );
+ }
+ try {
+ return thisClass.getDeclaredField( fieldName );
+ }
+ catch ( NoSuchFieldException e ) {
+ return getField( thisClass.getSuperclass(), fieldName );
+ }
+ }
+
+
+ /**
+ * Object rape: fondle the private parts of an object without it's
+ * permission.
+ *
+ * @param instance the object instance
+ * @param fieldName the name of the field
+ * @return an object representing the value of the
+ * field
+ * @exception IllegalAccessException foiled by the security manager
+ * @exception NoSuchFieldException Darn, nothing to fondle
+ */
+ private Object getValue( Object instance, String fieldName )
+ throws IllegalAccessException, NoSuchFieldException {
+ Field field = getField( instance.getClass(), fieldName );
+ field.setAccessible( true );
+ return field.get( instance );
+ }
+
+
+ /**
+ * load variables from a file
+ *
+ * @param file file to load
+ * @exception BuildException Description of the Exception
+ */
+ private void loadFile( File file ) throws BuildException {
+ Properties props = new Properties();
+ try {
+ if ( file.exists() ) {
+ FileInputStream fis = new FileInputStream( file );
+ try {
+ props.load( fis );
+ }
+ finally {
+ if ( fis != null ) {
+ fis.close();
+ }
+ }
+ addProperties( props );
+ }
+ else {
+ log( "Unable to find property file: " + file.getAbsolutePath(),
+ Project.MSG_VERBOSE );
+ }
+ }
+ catch ( IOException ex ) {
+ throw new BuildException( ex, location );
+ }
+ }
+
+
+ /**
+ * iterate through a set of properties, resolve them, then assign them
+ *
+ * @param props The feature to be added to the Properties attribute
+ */
+ protected void addProperties( Properties props ) {
+ resolveAllProperties( props );
+ Enumeration e = props.keys();
+ while ( e.hasMoreElements() ) {
+ String name = ( String ) e.nextElement();
+ String value = props.getProperty( name );
+ forceProperty( name, value );
+ }
+ }
+
+
+ /**
+ * resolve properties inside a properties hashtable
+ *
+ * @param props properties object to resolve
+ * @exception BuildException Description of the Exception
+ */
+ private void resolveAllProperties( Properties props ) throws BuildException {
+ for ( Enumeration e = props.keys(); e.hasMoreElements(); ) {
+ String name = ( String ) e.nextElement();
+ String value = props.getProperty( name );
+
+ boolean resolved = false;
+ while ( !resolved ) {
+ Vector fragments = new Vector();
+ Vector propertyRefs = new Vector();
+ ProjectHelper.parsePropertyString( value, fragments,
+ propertyRefs );
+
+ resolved = true;
+ if ( propertyRefs.size() != 0 ) {
+ StringBuffer sb = new StringBuffer();
+ Enumeration i = fragments.elements();
+ Enumeration j = propertyRefs.elements();
+ while ( i.hasMoreElements() ) {
+ String fragment = ( String ) i.nextElement();
+ if ( fragment == null ) {
+ String propertyName = ( String ) j.nextElement();
+ if ( propertyName.equals( name ) ) {
+ throw new BuildException( "Property " + name
+ + " was circularly "
+ + "defined." );
+ }
+ fragment = getProject().getProperty( propertyName );
+ if ( fragment == null ) {
+ if ( props.containsKey( propertyName ) ) {
+ fragment = props.getProperty( propertyName );
+ resolved = false;
+ }
+ else {
+ fragment = "${" + propertyName + "}";
+ }
+ }
+ }
+ sb.append( fragment );
+ }
+ value = sb.toString();
+ props.put( name, value );
+ }
+ }
+ }
+ }
+
+}
+
diff --git a/src/java/net/sf/antcontrib/util/Reflector.java b/src/java/net/sf/antcontrib/util/Reflector.java
new file mode 100644
index 0000000..ab6decc
--- /dev/null
+++ b/src/java/net/sf/antcontrib/util/Reflector.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.sf.antcontrib.util;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import org.apache.tools.ant.BuildException;
+
+/**
+ * Utility class to handle reflection on java objects.
+ * Its main purpose is to allow ant-contrib classes
+ * to compile under ant1.5 but allow the classes to
+ * use ant1.6 classes and code if present.
+ * The class is a holder class for an object and
+ * uses java reflection to call methods on the objects.
+ * If things go wrong, BuildExceptions are thrown.
+ * @author Peter Reilly
+ */
+
+public class Reflector {
+ private Object obj;
+ /**
+ * Constructor for the wrapper using a classname
+ * @param name the classname of the object to construct.
+ */
+ public Reflector(String name) {
+ try {
+ Class clazz;
+ clazz = Class.forName(name);
+ Constructor constructor;
+ constructor = clazz.getConstructor(new Class[]{});
+ obj = constructor.newInstance(new Object[]{});
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Constructor using a passed in object.
+ * @param obj the object to wrap.
+ */
+
+ public Reflector(Object obj) {
+ this.obj = obj;
+ }
+
+ /**
+ * @return the wrapped object.
+ */
+ public Object getObject() {
+ return obj;
+ }
+
+ /**
+ * Call a method on the object with no parameters.
+ * @param methodName the name of the method to call
+ * @return the object returned by the method
+ */
+ public Object call(String methodName) {
+ try {
+ Method method;
+ method = obj.getClass().getMethod(
+ methodName, new Class[] {});
+ return method.invoke(obj, new Object[] {});
+ } catch (InvocationTargetException t) {
+ Throwable t2 = t.getTargetException();
+ if (t2 instanceof BuildException) {
+ throw (BuildException) t2;
+ }
+ throw new BuildException(t2);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Call a method with an object using a specific
+ * type as for the method parameter.
+ * @param methodName the name of the method
+ * @param className the name of the class of the parameter of the method
+ * @param o the object to use as the argument of the method
+ * @return the object returned by the method
+ */
+ public Object callExplicit(
+ String methodName, String className, Object o) {
+ try {
+ Method method;
+ Class clazz = Class.forName(className);
+ method = obj.getClass().getMethod(
+ methodName, new Class[] {clazz});
+ return method.invoke(obj, new Object[] {o});
+ } catch (InvocationTargetException t) {
+ Throwable t2 = t.getTargetException();
+ if (t2 instanceof BuildException) {
+ throw (BuildException) t2;
+ }
+ throw new BuildException(t2);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Call a method with an object using a specific
+ * type as for the method parameter.
+ * @param methodName the name of the method
+ * @param classType the class of the parameter of the method
+ * @param o the object to use as the argument of the method
+ * @return the object returned by the method
+ */
+ public Object callExplicit(
+ String methodName, Class classType, Object o) {
+ try {
+ Method method;
+ method = obj.getClass().getMethod(
+ methodName, new Class[] {classType});
+ return method.invoke(obj, new Object[] {o});
+ } catch (InvocationTargetException t) {
+ Throwable t2 = t.getTargetException();
+ if (t2 instanceof BuildException) {
+ throw (BuildException) t2;
+ }
+ throw new BuildException(t2);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Call a method with one parameter.
+ * @param methodName the name of the method to call
+ * @param o the object to use as the parameter, this must
+ * be of the same type as the method parameter (not a subclass).
+ * @return the object returned by the method
+ */
+ public Object call(String methodName, Object o) {
+ try {
+ Method method;
+ method = obj.getClass().getMethod(
+ methodName, new Class[] {o.getClass()});
+ return method.invoke(obj, new Object[] {o});
+ } catch (InvocationTargetException t) {
+ Throwable t2 = t.getTargetException();
+ if (t2 instanceof BuildException) {
+ throw (BuildException) t2;
+ }
+ throw new BuildException(t2);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+
+ /**
+ * Call a method with two parameters.
+ * @param methodName the name of the method to call
+ * @param o1 the object to use as the first parameter, this must
+ * be of the same type as the method parameter (not a subclass).
+ * @param o2 the object to use as the second parameter, this must
+ * be of the same type as the method parameter (not a subclass).
+ * @return the object returned by the method
+ */
+ public Object call(String methodName, Object o1, Object o2) {
+ try {
+ Method method;
+ method = obj.getClass().getMethod(
+ methodName, new Class[] {o1.getClass(), o2.getClass()});
+ return method.invoke(obj, new Object[] {o1, o2});
+ } catch (InvocationTargetException t) {
+ Throwable t2 = t.getTargetException();
+ if (t2 instanceof BuildException) {
+ throw (BuildException) t2;
+ }
+ throw new BuildException(t2);
+ } catch (Throwable t) {
+ throw new BuildException(t);
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/util/ThreadPool.java b/src/java/net/sf/antcontrib/util/ThreadPool.java
new file mode 100644
index 0000000..f8b25b3
--- /dev/null
+++ b/src/java/net/sf/antcontrib/util/ThreadPool.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.util;
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class ThreadPool
+{
+ private int maxActive;
+ private int active;
+
+
+ public ThreadPool(int maxActive)
+ {
+ super();
+ this.maxActive = maxActive;
+ this.active = 0;
+ }
+
+ public void returnThread(ThreadPoolThread thread)
+ {
+ synchronized (this)
+ {
+ active--;
+ notify();
+ }
+ }
+
+
+ public ThreadPoolThread borrowThread()
+ throws InterruptedException
+ {
+ synchronized (this)
+ {
+ if (maxActive > 0 && active >= maxActive)
+ {
+ wait();
+ }
+
+ active++;
+ return new ThreadPoolThread(this);
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/util/ThreadPoolThread.java b/src/java/net/sf/antcontrib/util/ThreadPoolThread.java
new file mode 100644
index 0000000..6170ee4
--- /dev/null
+++ b/src/java/net/sf/antcontrib/util/ThreadPoolThread.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.util;
+
+
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author <a href='mailto:[email protected]'>Matthew Inger</a>
+ *
+ ****************************************************************************/
+
+
+public class ThreadPoolThread
+ extends Thread
+{
+
+ private ThreadPool pool;
+ private Runnable runnable;
+
+ public ThreadPoolThread(ThreadPool pool)
+ {
+ super();
+ this.pool = pool;
+ }
+
+ public void setRunnable(Runnable runnable)
+ {
+ this.runnable = runnable;
+ }
+
+
+ public void run()
+ {
+ try
+ {
+ if (runnable != null)
+ runnable.run();
+ }
+ finally
+ {
+ try
+ {
+ pool.returnThread(this);
+ }
+ catch (Exception e)
+ {
+ ; // gulp;
+ }
+ }
+ }
+}
diff --git a/src/java/net/sf/antcontrib/walls/CompileWithWalls.java b/src/java/net/sf/antcontrib/walls/CompileWithWalls.java
new file mode 100644
index 0000000..4b6548f
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/CompileWithWalls.java
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.Task;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.taskdefs.Javac;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.JAXPUtils;
+import org.xml.sax.HandlerBase;
+import org.xml.sax.Parser;
+import org.xml.sax.SAXException;
+/*
+ * Created on Aug 24, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class CompileWithWalls extends Task {
+ private boolean setWallsTwice = false;
+ private boolean setJavacTwice = false;
+ private Walls walls;
+ private Javac javac;
+ private File wallsFile;
+ private File tempBuildDir;
+
+ private Map packagesNeedingCompiling = new HashMap();
+
+ private SAXException cachedSAXException = null;
+ private IOException cachedIOException = null;
+
+ public void setIntermediaryBuildDir(File f) {
+ tempBuildDir = f;
+ }
+
+ public File getIntermediaryBuildDir() {
+ return tempBuildDir;
+ }
+
+ public void setWalls(File f) {
+ this.wallsFile = f;
+
+ Parser parser = JAXPUtils.getParser();
+ HandlerBase hb = new WallsFileHandler(this, wallsFile);
+ parser.setDocumentHandler(hb);
+ parser.setEntityResolver(hb);
+ parser.setErrorHandler(hb);
+ parser.setDTDHandler(hb);
+ try {
+ log("about to start parsing walls file", Project.MSG_INFO);
+ parser.parse(wallsFile.toURL().toExternalForm());
+ } catch (SAXException e) {
+ cachedSAXException = e;
+ throw new ParsingWallsException("Problem parsing walls file attached:", e);
+ } catch (IOException e) {
+ cachedIOException = e;
+ throw new ParsingWallsException("IOException on walls file attached:", e);
+ }
+ }
+
+ public File getWalls() {
+ return wallsFile;
+ }
+
+
+ public Walls createWalls() {
+ if (walls != null)
+ setWallsTwice = true;
+ walls = new Walls();
+ return walls;
+ }
+ public Javac createJavac() {
+ if (javac != null)
+ setJavacTwice = true;
+ javac = new Javac();
+ return javac;
+ }
+ public void execute() throws BuildException {
+ if(cachedIOException != null)
+ throw new BuildException(cachedIOException, getLocation());
+ else if(cachedSAXException != null)
+ throw new BuildException(cachedSAXException, getLocation());
+ else if(tempBuildDir == null)
+ throw new BuildException(
+ "intermediaryBuildDir attribute must be specified on the compilewithwalls element"
+ , getLocation());
+ else if (javac == null)
+ throw new BuildException(
+ "There must be a nested javac element",
+ getLocation());
+ else if (walls == null)
+ throw new BuildException(
+ "There must be a nested walls element",
+ getLocation());
+ else if (setWallsTwice)
+ throw new BuildException(
+ "compilewithwalls task only supports one nested walls element or one walls attribute",
+ getLocation());
+ else if (setJavacTwice)
+ throw new BuildException(
+ "compilewithwalls task only supports one nested javac element",
+ getLocation());
+
+ getProject().addTaskDefinition("SilentMove", SilentMove.class);
+ getProject().addTaskDefinition("SilentCopy", SilentCopy.class);
+
+ File destDir = javac.getDestdir();
+ Path src = javac.getSrcdir();
+
+ if(src == null)
+ throw new BuildException("Javac inside compilewithwalls must have a srcdir specified");
+
+ String[] list = src.list();
+ File[] tempSrcDirs1 = new File[list.length];
+ for(int i = 0; i < list.length; i++) {
+ tempSrcDirs1[i] = getProject().resolveFile(list[i]);
+ }
+
+ String[] classpaths = new String[0];
+ if(javac.getClasspath() != null)
+ classpaths = javac.getClasspath().list();
+
+ File temp = null;
+ for(int i = 0; i < classpaths.length; i++) {
+ temp = new File(classpaths[i]);
+ if(temp.isDirectory()) {
+
+ for(int n = 0; n < tempSrcDirs1.length; n++) {
+ if(tempSrcDirs1[n].compareTo(temp) == 0)
+ throw new BuildException("The classpath cannot contain any of the\n"
+ +"src directories, but it does.\n"
+ +"srcdir="+tempSrcDirs1[n]);
+ }
+ }
+ }
+
+ //get rid of non-existent srcDirs
+ List srcDirs2 = new ArrayList();
+ for(int i = 0; i < tempSrcDirs1.length; i++) {
+ if(tempSrcDirs1[i].exists())
+ srcDirs2.add(tempSrcDirs1[i]);
+ }
+
+ if (destDir == null)
+ throw new BuildException(
+ "destdir was not specified in nested javac task",
+ getLocation());
+
+ //make sure tempBuildDir is not inside destDir or we are in trouble!!
+ if(file1IsChildOfFile2(tempBuildDir, destDir))
+ throw new BuildException("intermediaryBuildDir attribute cannot be specified\n"
+ +"to be the same as destdir or inside desdir of the javac task.\n"
+ +"This is an intermediary build directory only used by the\n"
+ +"compilewithwalls task, not the class file output directory.\n"
+ +"The class file output directory is specified in javac's destdir attribute", getLocation());
+
+ //create the tempBuildDir if it doesn't exist.
+ if(!tempBuildDir.exists()) {
+ tempBuildDir.mkdirs();
+ log("created direction="+tempBuildDir, Project.MSG_VERBOSE);
+ }
+
+ Iterator iter = walls.getPackagesToCompile();
+ while (iter.hasNext()) {
+ Package toCompile = (Package)iter.next();
+
+ File buildSpace = toCompile.getBuildSpace(tempBuildDir);
+ if(!buildSpace.exists()) {
+ buildSpace.mkdir();
+ log("created directory="+buildSpace, Project.MSG_VERBOSE);
+ }
+
+ FileSet javaIncludes2 =
+ toCompile.getJavaCopyFileSet(getProject(), getLocation());
+
+ for(int i = 0; i < srcDirs2.size(); i++) {
+ File srcDir = (File)srcDirs2.get(i);
+ javaIncludes2.setDir(srcDir);
+ log(toCompile.getPackage()+": sourceDir["+i+"]="+srcDir+" destDir="+buildSpace, Project.MSG_VERBOSE);
+ copyFiles(srcDir, buildSpace, javaIncludes2);
+ }
+
+ Path srcDir2 = toCompile.getSrcPath(tempBuildDir, getProject());
+ Path classPath = toCompile.getClasspath(tempBuildDir, getProject());
+ if(javac.getClasspath() != null)
+ classPath.addExisting(javac.getClasspath());
+
+ //unfortunately, we cannot clear the SrcDir in Javac, so we have to clone
+ //instead of just reusing the other Javac....this means added params in
+ //future releases will be missed unless this task is kept up to date.
+ //need to convert to reflection later so we don't need to keep this up to
+ //date.
+ Javac buildSpaceJavac = new Javac();
+ buildSpaceJavac.setProject(getProject());
+ buildSpaceJavac.setOwningTarget(getOwningTarget());
+ buildSpaceJavac.setTaskName(getTaskName());
+ log(toCompile.getPackage()+": Compiling");
+ log(toCompile.getPackage()+": sourceDir="+srcDir2, Project.MSG_VERBOSE);
+ log(toCompile.getPackage()+": classPath="+classPath, Project.MSG_VERBOSE);
+ log(toCompile.getPackage()+": destDir="+buildSpace, Project.MSG_VERBOSE);
+ buildSpaceJavac.setSrcdir(srcDir2);
+ buildSpaceJavac.setDestdir(buildSpace);
+ //includes not used...ie. ignored
+ //includesfile not used
+ //excludes not used
+ //excludesfile not used
+ buildSpaceJavac.setClasspath(classPath);
+ //sourcepath not used
+ buildSpaceJavac.setBootclasspath(javac.getBootclasspath());
+ //classpath not used..redefined by us
+ //sourcepathref not used...redefined by us.
+ //bootclasspathref was already copied above(see javac and you will understand)
+ buildSpaceJavac.setExtdirs(javac.getExtdirs());
+ buildSpaceJavac.setEncoding(javac.getEncoding());
+ buildSpaceJavac.setNowarn(javac.getNowarn());
+ buildSpaceJavac.setDebug(javac.getDebug());
+ buildSpaceJavac.setDebugLevel(javac.getDebugLevel());
+ buildSpaceJavac.setOptimize(javac.getOptimize());
+ buildSpaceJavac.setDeprecation(javac.getDeprecation());
+ buildSpaceJavac.setTarget(javac.getTarget());
+ buildSpaceJavac.setVerbose(javac.getVerbose());
+ buildSpaceJavac.setDepend(javac.getDepend());
+ buildSpaceJavac.setIncludeantruntime(javac.getIncludeantruntime());
+ buildSpaceJavac.setIncludejavaruntime(javac.getIncludejavaruntime());
+ buildSpaceJavac.setFork(javac.isForkedJavac());
+ buildSpaceJavac.setExecutable(javac.getJavacExecutable());
+ buildSpaceJavac.setMemoryInitialSize(javac.getMemoryInitialSize());
+ buildSpaceJavac.setMemoryMaximumSize(javac.getMemoryMaximumSize());
+ buildSpaceJavac.setFailonerror(javac.getFailonerror());
+ buildSpaceJavac.setSource(javac.getSource());
+ buildSpaceJavac.setCompiler(javac.getCompiler());
+
+ Javac.ImplementationSpecificArgument arg;
+ String[] args = javac.getCurrentCompilerArgs();
+ if(args != null) {
+ for(int i = 0; i < args.length;i++) {
+ arg = buildSpaceJavac.createCompilerArg();
+ arg.setValue(args[i]);
+ }
+ }
+
+ buildSpaceJavac.setProject(getProject());
+ buildSpaceJavac.perform();
+
+ //copy class files to javac's destDir where the user wants the class files
+ copyFiles(buildSpace, destDir, toCompile.getClassCopyFileSet(getProject(), getLocation()));
+ }
+ }
+ /**
+ * @param tempBuildDir
+ * @param destDir
+ * @return
+ */
+ private boolean file1IsChildOfFile2(File tempBuildDir, File destDir) {
+ File parent = tempBuildDir;
+ for(int i = 0; i < 1000; i++) {
+ if(parent.compareTo(destDir) == 0)
+ return true;
+ parent = parent.getParentFile();
+ if(parent == null)
+ return false;
+ }
+
+ throw new RuntimeException("You either have more than 1000 directories in"
+ +"\nyour heirarchy or this is a bug, please report. parent="+parent+" destDir="+destDir);
+ }
+
+ /**
+ * Move java or class files to temp files or moves the temp files
+ * back to java or class files. This must be done because javac
+ * is too nice and sticks already compiled classes and ones depended
+ * on in the classpath destroying the compile time wall. This way,
+ * we can keep the wall up.
+ *
+ * @param srcDir Directory to copy files from/to(Usually the java files dir or the class files dir)
+ * @param fileset The fileset of files to include in the move.
+ * @param moveToTempFile true if moving src files to temp files, false if moving temp files
+ * back to src files.
+ * @param isJavaFiles true if we are moving .java files, false if we are moving .class files.
+ */
+ private void copyFiles(
+ File srcDir,
+ File destDir,
+ FileSet fileset) {
+
+ fileset.setDir(srcDir);
+ if (!srcDir.exists())
+ throw new BuildException(
+ "Directory=" + srcDir + " does not exist",
+ getLocation());
+
+
+ //before we do this, we have to move all files not
+ //in the above fileset to xxx.java.ant-tempfile
+ //so that they don't get dragged into the compile
+ //This way we don't miss anything and all the dependencies
+ //are listed or the compile will break.
+ Copy move = (Copy)getProject().createTask("SilentCopy");
+ move.setProject(getProject());
+ move.setOwningTarget(getOwningTarget());
+ move.setTaskName(getTaskName());
+ move.setLocation(getLocation());
+ move.setTodir(destDir);
+// move.setOverwrite(true);
+ move.addFileset(fileset);
+ move.perform();
+ }
+
+ public void log(String msg, int level) {
+ super.log(msg, level);
+ }
+
+ //until 1.3 is deprecated, this is a cheat to chain exceptions.
+ private class ParsingWallsException extends RuntimeException {
+
+ private String message;
+
+ public ParsingWallsException(String message, Throwable cause) {
+ super(message);
+
+ this.message = message+"\n";
+
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ cause.printStackTrace(pw);
+
+ this.message += sw;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public String toString() {
+ return getMessage();
+ }
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/walls/Package.java b/src/java/net/sf/antcontrib/walls/Package.java
new file mode 100644
index 0000000..502b196
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/Package.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import java.io.File;
+import java.util.StringTokenizer;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.Path;
+
+
+/*
+ * Created on Aug 24, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class Package {
+
+ private String name;
+ private String pack;
+
+ //signifies the package did not end with .* or .**
+ private boolean badPackage = false;
+ private String failureReason = null;
+
+ //holds the name attribute of the package element of each
+ //package this package depends on.
+ private String[] depends;
+
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+
+ public void setPackage(String pack) {
+ this.pack = pack;
+ }
+ public String getPackage() {
+ return pack;
+ }
+
+ public void setDepends(String d) {
+ if(d == null) {
+ throw new RuntimeException("depends cannot be set to null");
+ }
+
+ //parse this first.
+ StringTokenizer tok = new StringTokenizer(d, ", \t");
+ depends = new String[tok.countTokens()];
+ int i = 0;
+ while(tok.hasMoreTokens()) {
+ depends[i] = tok.nextToken();
+ i++;
+ }
+ }
+
+ public String[] getDepends() {
+ return depends;
+ }
+
+ /**
+ * FILL IN JAVADOC HERE
+ *
+ */
+ public FileSet getJavaCopyFileSet(Project p, Location l) throws BuildException {
+
+ if(failureReason != null)
+ throw new BuildException(failureReason, l);
+ else if(pack.indexOf("/") != -1 || pack.indexOf("\\") != -1)
+ throw new BuildException("A package name cannot contain '\\' or '/' like package="+pack
+ +"\nIt must look like biz.xsoftware.* for example", l);
+ FileSet set = new FileSet();
+
+ String match = getMatch(p, pack, ".java");
+ //log("match="+match+" pack="+pack);
+ //first exclude the compilation module, then exclude all it's
+ //dependencies too.
+ set.setIncludes(match);
+
+ return set;
+ }
+
+ /**
+ * FILL IN JAVADOC HERE
+ *
+ */
+ public FileSet getClassCopyFileSet(Project p, Location l) throws BuildException {
+ FileSet set = new FileSet();
+ set.setIncludes("**/*.class");
+ return set;
+ }
+
+ public File getBuildSpace(File baseDir) {
+ return new File(baseDir, name);
+ }
+
+ /**
+ * @return the source path
+ */
+ public Path getSrcPath(File baseDir, Project p) {
+ Path path = new Path(p);
+
+ path.setLocation(getBuildSpace(baseDir));
+ return path;
+ }
+
+ /**
+ * @return the classpath
+ */
+ public Path getClasspath(File baseDir, Project p) {
+ Path path = new Path(p);
+
+ if(depends != null) {
+ for(int i = 0; i < depends.length; i++) {
+ String buildSpace = (String)depends[i];
+
+ File dependsDir = new File(baseDir, buildSpace);
+ path.setLocation(dependsDir);
+ }
+ }
+ return path;
+ }
+
+ private String getMatch(Project p, String pack, String postFix) {
+ pack = p.replaceProperties(pack);
+
+
+ pack = pack.replace('.', File.separatorChar);
+
+ String match;
+ String classMatch;
+ if(pack.endsWith("**")) {
+ match = pack + File.separatorChar+"*"+postFix;
+ }
+ else if(pack.endsWith("*")) {
+ match = pack + postFix;
+ }
+ else
+ throw new RuntimeException("Please report this bug");
+
+ return match;
+ }
+
+ /**
+ * FILL IN JAVADOC HERE
+ * @param r a fault reason string
+ */
+ public void setFaultReason(String r) {
+ failureReason = r;
+ }
+}
diff --git a/src/java/net/sf/antcontrib/walls/SilentCopy.java b/src/java/net/sf/antcontrib/walls/SilentCopy.java
new file mode 100644
index 0000000..d188952
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/SilentCopy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Copy;
+
+/*
+ * Created on Aug 25, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class SilentCopy extends Copy {
+
+ public void log(String msg) {
+ log(msg, Project.MSG_INFO);
+ }
+
+ public void log(String msg, int level) {
+ if(level == Project.MSG_INFO)
+ super.log(msg, Project.MSG_VERBOSE);
+ else if(level == Project.MSG_VERBOSE)
+ super.log(msg, Project.MSG_DEBUG);
+
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/walls/SilentMove.java b/src/java/net/sf/antcontrib/walls/SilentMove.java
new file mode 100644
index 0000000..721472a
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/SilentMove.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Move;
+
+/*
+ * Created on Aug 25, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class SilentMove extends Move {
+
+ public void log(String msg) {
+ log(msg, Project.MSG_INFO);
+ }
+
+ public void log(String msg, int level) {
+ if(level == Project.MSG_INFO)
+ super.log(msg, Project.MSG_VERBOSE);
+ else if(level == Project.MSG_VERBOSE)
+ super.log(msg, Project.MSG_DEBUG);
+
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/walls/Walls.java b/src/java/net/sf/antcontrib/walls/Walls.java
new file mode 100644
index 0000000..dda11cf
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/Walls.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import java.util.*;
+
+
+/*
+ * Created on Aug 24, 2003
+ *
+ * To change the template for this generated file go to
+ * Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments
+ */
+/**
+ * FILL IN JAVADOC HERE
+ *
+ * @author Dean Hiller([email protected])
+ */
+public class Walls {
+
+ private List packages = new LinkedList();
+ private Map nameToPackage = new HashMap();
+
+ public Package getPackage(String name) {
+ return (Package)nameToPackage.get(name);
+ }
+
+ public void addConfiguredPackage(Package p) {
+
+ String pack = p.getPackage();
+ if(!pack.endsWith(".*") && !pack.endsWith(".**"))
+ p.setFaultReason("The package='"+pack+"' must end with "
+ +".* or .** such as biz.xsoftware.* or "
+ +"biz.xsoftware.**");
+
+ String[] depends = p.getDepends();
+ if(depends == null) {
+ nameToPackage.put(p.getName(), p);
+ packages.add(p);
+ return;
+ }
+
+ //make sure all depends are in Map first
+ //circular references then are not a problem because they must
+ //put the stuff in order
+ for(int i = 0; i < depends.length; i++) {
+ Package dependsPackage = (Package)nameToPackage.get(depends[i]);
+
+ if(dependsPackage == null) {
+ p.setFaultReason("package name="+p.getName()+" did not have "
+ +depends[i]+" listed before it and cannot compile without it");
+ }
+ }
+
+ nameToPackage.put(p.getName(), p);
+ packages.add(p);
+ }
+
+ public Iterator getPackagesToCompile() {
+ //must return the list, as we need to process in order, so unfortunately
+ //we cannot pass back an iterator from the hashtable because that would
+ //be unordered and would break.
+ return packages.iterator();
+ }
+} \ No newline at end of file
diff --git a/src/java/net/sf/antcontrib/walls/WallsFileHandler.java b/src/java/net/sf/antcontrib/walls/WallsFileHandler.java
new file mode 100644
index 0000000..f9e8f65
--- /dev/null
+++ b/src/java/net/sf/antcontrib/walls/WallsFileHandler.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import java.io.File;
+
+import org.apache.tools.ant.Project;
+import org.xml.sax.*;
+
+
+/**
+ * Handler for the root element. Its only child must be the "project" element.
+ */
+class WallsFileHandler extends HandlerBase {
+
+ private final CompileWithWalls compilewithwalls;
+ private File file = null;
+ private Walls walls = null;
+ private Locator locator = null;
+
+ /**
+ * @param CompileWithWalls
+ */
+ WallsFileHandler(CompileWithWalls walls, File file) {
+ this.compilewithwalls = walls;
+ this.file = file;
+ }
+
+ /**
+ * Resolves file: URIs relative to the build file.
+ *
+ * @param publicId The public identifer, or <code>null</code>
+ * if none is available. Ignored in this
+ * implementation.
+ * @param systemId The system identifier provided in the XML
+ * document. Will not be <code>null</code>.
+ */
+ public InputSource resolveEntity(String publicId,
+ String systemId) {
+ compilewithwalls.log("publicId="+publicId+" systemId="+systemId,
+ Project.MSG_VERBOSE);
+ return null;
+ }
+
+ /**
+ * Handles the start of a project element. A project handler is created
+ * and initialised with the element name and attributes.
+ *
+ * @param tag The name of the element being started.
+ * Will not be <code>null</code>.
+ * @param attrs Attributes of the element being started.
+ * Will not be <code>null</code>.
+ *
+ * @exception SAXParseException if the tag given is not
+ * <code>"project"</code>
+ */
+ public void startElement(String name, AttributeList attrs) throws SAXParseException {
+ if (name.equals("walls")) {
+ if(attrs.getLength() > 0)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", no attributes allowed for walls element", locator);
+ walls = this.compilewithwalls.createWalls();
+ } else if (name.equals("package")) {
+ handlePackage(attrs);
+ } else {
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", Unexpected element \"" + name + "\"", locator);
+ }
+ }
+
+ private void handlePackage(AttributeList attrs) throws SAXParseException {
+ if(walls == null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", package element must be nested in a walls element", locator);
+
+ String name = attrs.getValue("name");
+ String thePackage = attrs.getValue("package");
+ String depends = attrs.getValue("depends");
+ if(name == null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", package element must contain the 'name' attribute", locator);
+ else if(thePackage == null)
+ throw new SAXParseException("Error in file="+file.getAbsolutePath()
+ +", package element must contain the 'package' attribute", locator);
+
+ Package p = new Package();
+ p.setName(name);
+ p.setPackage(thePackage);
+ if(depends != null)
+ p.setDepends(depends);
+
+ walls.addConfiguredPackage(p);
+ }
+ /**
+ * Sets the locator in the project helper for future reference.
+ *
+ * @param locator The locator used by the parser.
+ * Will not be <code>null</code>.
+ */
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+} \ No newline at end of file
diff --git a/test/resources/antclipse/.classpath b/test/resources/antclipse/.classpath
new file mode 100644
index 0000000..8a55b01
--- /dev/null
+++ b/test/resources/antclipse/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <!-- this is an awfully hacked Eclipse classpath file, must find a way to test libs-->
+ <classpathentry kind="src" path="../../../src"/>
+ <classpathentry kind="src" path="../../../test/src"/>
+ <classpathentry kind="src" path="../../../test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="."/>
+</classpath>
diff --git a/test/resources/antclipse/antclipsetest.xml b/test/resources/antclipse/antclipsetest.xml
new file mode 100644
index 0000000..460bbad
--- /dev/null
+++ b/test/resources/antclipse/antclipsetest.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<project default="everything" name="Antclipse test xml file" basedir=".">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+<target name="make.fs.output">
+ <!-- creates a fileset including all the files from the output directory, called ecl1-bin if your binary directory is bin/ -->
+ <antclipse produce="fileset" idcontainer="ecl1" includeoutput="true" includesource="false"
+ includelibs="false" verbose="true"/>
+</target>
+
+<target name="make.fs.sources">
+ <!-- creates a fileset for each source directory, called ecl2-*source-dir-name*/ -->
+ <antclipse produce="fileset" idcontainer="ecl2" includeoutput="false" includesource="true"
+ includelibs="false" verbose="true"/>
+</target>
+
+<target name="make.fs.libs">
+ <!-- creates a fileset sontaining all your project libs called ecl3/ -->
+ <antclipse produce="fileset" idcontainer="ecl3" verbose="true"/>
+</target>
+
+<target name="make.cp">
+ <!-- creates a fileset sontaining all your project libs called ecl3/ -->
+ <antclipse produce="classpath" idcontainer="eclp" verbose="true" includeoutput="true"/>
+</target>
+
+<target name="everything" depends="make.fs.libs, make.fs.output, make.fs.sources, make.cp">
+ <echo message="The output path is ${ecl1outpath}"/>
+ <echo message="The source path is ${ecl2srcpath}"/>
+ <!-- makes a jar file with the content of the output directory -->
+ <zip destfile="out.jar"><fileset refid="ecl1-${ecl1outpath}"/></zip>
+ <!-- makes a zip file with all your sources (supposing you have only source directory) -->
+ <zip destfile="src.zip"><fileset refid="ecl2-${ecl2srcpath}"/></zip>
+ <!-- makes a big zip file with all your project libraries -->
+ <zip destfile="libs.zip"><fileset refid="ecl3"/></zip>
+ <!-- imports the classpath into a property then echoes the property -->
+ <property name="cpcontent" refid="eclp"/>
+ <echo>The newly created classpath is ${cpcontent}</echo>
+</target>
+</project> \ No newline at end of file
diff --git a/test/resources/antserver/antservertest.xml b/test/resources/antserver/antservertest.xml
new file mode 100644
index 0000000..77f8db0
--- /dev/null
+++ b/test/resources/antserver/antservertest.xml
@@ -0,0 +1,138 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="Project" default="default" basedir=".">
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
+
+ <property name="server.host" value="localhost" />
+ <property name="server.port" value="17000" />
+
+ <target name="default">
+ </target>
+
+ <!-- =============================================== -->
+ <!-- TEST 1 -->
+ <!-- =============================================== -->
+ <target name="test1_remote">
+ <echo message="Test1 Successfully Called" />
+ </target>
+
+ <target name="dotest1">
+ <remoteant machine="${server.host}" port="${server.port}">
+ <runtarget target="test1_remote">
+ </runtarget>
+ </remoteant>
+ </target>
+
+ <target name="test1">
+ <antcall target="run.test.with.server">
+ <param name="test.target" value="dotest1" />
+ </antcall>
+ </target>
+
+ <!-- =============================================== -->
+ <!-- TEST 2 -->
+ <!-- =============================================== -->
+ <target name="test2_remote">
+ <echo message="${message}" />
+ </target>
+
+ <target name="dotest2">
+ <remoteant machine="${server.host}" port="${server.port}">
+ <runtarget target="test2_remote">
+ <property name="message" value="Test2 Successfully Called" />
+ </runtarget>
+ </remoteant>
+ </target>
+
+ <target name="test2">
+ <antcall target="run.test.with.server">
+ <param name="test.target" value="dotest2" />
+ </antcall>
+ </target>
+
+ <!-- =============================================== -->
+ <!-- TEST 3 -->
+ <!-- =============================================== -->
+ <target name="test3_remote">
+ <touch file="E:/test3.txt" />
+ <echo message="Test3 Successfully Called" />
+ </target>
+
+ <target name="dotest3">
+ <remoteant machine="${server.host}" port="${server.port}">
+ <runant target="test3_remote" antfile="${ant.file}">
+ </runant>
+ </remoteant>
+ </target>
+
+ <target name="test3">
+ <antcall target="run.test.with.server">
+ <param name="test.target" value="dotest3" />
+ </antcall>
+ </target>
+
+ <!-- =============================================== -->
+ <!-- TEST 4 -->
+ <!-- =============================================== -->
+ <target name="test4_remote">
+ <echo message="${message}" />
+ </target>
+
+ <target name="dotest4">
+ <remoteant machine="${server.host}" port="${server.port}">
+ <runant target="test4_remote" antfile="${ant.file}">
+ <property name="message" value="Test4 Successfully Called" />
+ </runant>
+ </remoteant>
+ </target>
+
+ <target name="test4">
+ <antcall target="run.test.with.server">
+ <param name="test.target" value="dotest4" />
+ </antcall>
+ </target>
+
+ <target name="dotest5">
+ <mkdir dir="servertests" />
+ <remoteant machine="${server.host}" port="${server.port}">
+ <sendfile file="clientfile.txt" todir="servertests" />
+ </remoteant>
+ <available property="file.available"
+ file="servertests/clientfile.txt" />
+ <fail unless="file.available" />
+ </target>
+
+ <target name="cleanup">
+ <delete quiet="yes" dir="servertests"/>
+ </target>
+
+ <target name="test5">
+ <antcall target="run.test.with.server">
+ <param name="test.target" value="dotest5" />
+ </antcall>
+ </target>
+ <target name="run.test.with.server">
+ <parallel>
+ <antserver port="${server.port}" />
+
+ <sequential>
+ <waitfor checkevery="500" checkeveryunit="millisecond">
+ <socket port="${server.port}" server="${server.host}" />
+ </waitfor>
+
+ <trycatch>
+ <try>
+ <antcall target="${test.target}" />
+ </try>
+ <finally>
+ <remoteant machine="${server.host}" port="${server.port}">
+ <shutdown />
+ </remoteant>
+ </finally>
+ </trycatch>
+ </sequential>
+ </parallel>
+ </target>
+
+
+</project>
diff --git a/test/resources/antserver/clientfile.txt b/test/resources/antserver/clientfile.txt
new file mode 100644
index 0000000..68f4931
--- /dev/null
+++ b/test/resources/antserver/clientfile.txt
@@ -0,0 +1 @@
+This is the file from the client.
diff --git a/test/resources/design/designfiles/arraydepend.xml b/test/resources/design/designfiles/arraydepend.xml
new file mode 100644
index 0000000..cdd0aeb
--- /dev/null
+++ b/test/resources/design/designfiles/arraydepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/arraydepend2.xml b/test/resources/design/designfiles/arraydepend2.xml
new file mode 100644
index 0000000..ab8d8e4
--- /dev/null
+++ b/test/resources/design/designfiles/arraydepend2.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend2"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/arraydepend3.xml b/test/resources/design/designfiles/arraydepend3.xml
new file mode 100644
index 0000000..1e30b7c
--- /dev/null
+++ b/test/resources/design/designfiles/arraydepend3.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend3"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/badxml.xml b/test/resources/design/designfiles/badxml.xml
new file mode 100644
index 0000000..63c82f0
--- /dev/null
+++ b/test/resources/design/designfiles/badxml.xml
@@ -0,0 +1,6 @@
+<design
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/castdepend.xml b/test/resources/design/designfiles/castdepend.xml
new file mode 100644
index 0000000..ac16d41
--- /dev/null
+++ b/test/resources/design/designfiles/castdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.castdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/catchdepend.xml b/test/resources/design/designfiles/catchdepend.xml
new file mode 100644
index 0000000..2ff6387
--- /dev/null
+++ b/test/resources/design/designfiles/catchdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.catchdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/declarejavautil.xml b/test/resources/design/designfiles/declarejavautil.xml
new file mode 100644
index 0000000..e2fb08e
--- /dev/null
+++ b/test/resources/design/designfiles/declarejavautil.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.declarejavautil"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/declarejavautilfail.xml b/test/resources/design/designfiles/declarejavautilfail.xml
new file mode 100644
index 0000000..fd43256
--- /dev/null
+++ b/test/resources/design/designfiles/declarejavautilfail.xml
@@ -0,0 +1,8 @@
+<design>
+<!-- needdeclarations is by default true, so we don't need that here -->
+<package name="javautil" package="java.util"/>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.declarejavautil"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/declarejavax.xml b/test/resources/design/designfiles/declarejavax.xml
new file mode 100644
index 0000000..f2b7d13
--- /dev/null
+++ b/test/resources/design/designfiles/declarejavax.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.declarejavax"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/declarejavaxpass.xml b/test/resources/design/designfiles/declarejavaxpass.xml
new file mode 100644
index 0000000..7e55849
--- /dev/null
+++ b/test/resources/design/designfiles/declarejavaxpass.xml
@@ -0,0 +1,7 @@
+<design>
+<package name="swing" package="javax.swing" needdeclarations="false"/>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.declarejavax"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/fielddepend.xml b/test/resources/design/designfiles/fielddepend.xml
new file mode 100644
index 0000000..409427c
--- /dev/null
+++ b/test/resources/design/designfiles/fielddepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.fielddepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/fieldrefdepend.xml b/test/resources/design/designfiles/fieldrefdepend.xml
new file mode 100644
index 0000000..3a04f6a
--- /dev/null
+++ b/test/resources/design/designfiles/fieldrefdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.fieldrefdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/innerclassdepend.xml b/test/resources/design/designfiles/innerclassdepend.xml
new file mode 100644
index 0000000..2be90f6
--- /dev/null
+++ b/test/resources/design/designfiles/innerclassdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.innerclassdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/instanceofdepend.xml b/test/resources/design/designfiles/instanceofdepend.xml
new file mode 100644
index 0000000..2e9a3f8
--- /dev/null
+++ b/test/resources/design/designfiles/instanceofdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.instanceofdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/interfacedepend.xml b/test/resources/design/designfiles/interfacedepend.xml
new file mode 100644
index 0000000..9f11581
--- /dev/null
+++ b/test/resources/design/designfiles/interfacedepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.interfacedepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/localvardepend.xml b/test/resources/design/designfiles/localvardepend.xml
new file mode 100644
index 0000000..518bae1
--- /dev/null
+++ b/test/resources/design/designfiles/localvardepend.xml
@@ -0,0 +1,9 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="factory" package="mod.temp" depends="dummy"/>
+<package name="client" package="mod.localvardepend">
+ <depends>factory</depends>
+</package>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/localvarrefdepend.xml b/test/resources/design/designfiles/localvarrefdepend.xml
new file mode 100644
index 0000000..6160330
--- /dev/null
+++ b/test/resources/design/designfiles/localvarrefdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.localvarrefdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/missingattribute.xml b/test/resources/design/designfiles/missingattribute.xml
new file mode 100644
index 0000000..5397c51
--- /dev/null
+++ b/test/resources/design/designfiles/missingattribute.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package package="mod.dummy"/>
+<package name="client" package="mod.arraydepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/multipleerrors.xml b/test/resources/design/designfiles/multipleerrors.xml
new file mode 100644
index 0000000..3c6780d
--- /dev/null
+++ b/test/resources/design/designfiles/multipleerrors.xml
@@ -0,0 +1,7 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend"/>
+<package name="client2" package="mod.catchdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/newdepend.xml b/test/resources/design/designfiles/newdepend.xml
new file mode 100644
index 0000000..b924645
--- /dev/null
+++ b/test/resources/design/designfiles/newdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.newdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/newdepend2.xml b/test/resources/design/designfiles/newdepend2.xml
new file mode 100644
index 0000000..4efc5bf
--- /dev/null
+++ b/test/resources/design/designfiles/newdepend2.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.newdepend2"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/nodebugoption.xml b/test/resources/design/designfiles/nodebugoption.xml
new file mode 100644
index 0000000..8ab00b7
--- /dev/null
+++ b/test/resources/design/designfiles/nodebugoption.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.nodebugoption"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/nojar.xml b/test/resources/design/designfiles/nojar.xml
new file mode 100644
index 0000000..cdd0aeb
--- /dev/null
+++ b/test/resources/design/designfiles/nojar.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.arraydepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/paramdepend.xml b/test/resources/design/designfiles/paramdepend.xml
new file mode 100644
index 0000000..4c24f4f
--- /dev/null
+++ b/test/resources/design/designfiles/paramdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.paramdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/passlocaldepend.xml b/test/resources/design/designfiles/passlocaldepend.xml
new file mode 100644
index 0000000..8544ed5
--- /dev/null
+++ b/test/resources/design/designfiles/passlocaldepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.passlocaldepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/pathelementpath.xml b/test/resources/design/designfiles/pathelementpath.xml
new file mode 100644
index 0000000..84bd103
--- /dev/null
+++ b/test/resources/design/designfiles/pathelementpath.xml
@@ -0,0 +1,7 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client1" package="mod.putstatic"/>
+<package name="client2" package="mod.arraydepend2"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/putstatic.xml b/test/resources/design/designfiles/putstatic.xml
new file mode 100644
index 0000000..92464e0
--- /dev/null
+++ b/test/resources/design/designfiles/putstatic.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.putstatic"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/recursion.xml b/test/resources/design/designfiles/recursion.xml
new file mode 100644
index 0000000..9aedd9e
--- /dev/null
+++ b/test/resources/design/designfiles/recursion.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="temp" package="mod.recursion.rec" subpackages="include"/>
+<package name="client" package="mod.recursion.client" depends="temp"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/recursion2.xml b/test/resources/design/designfiles/recursion2.xml
new file mode 100644
index 0000000..94b41cd
--- /dev/null
+++ b/test/resources/design/designfiles/recursion2.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="temp" package="mod.recursion2.dependency"/>
+<package name="client" package="mod.recursion2.rec" depends="temp" subpackages="include"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/recursion3.xml b/test/resources/design/designfiles/recursion3.xml
new file mode 100644
index 0000000..7fef148
--- /dev/null
+++ b/test/resources/design/designfiles/recursion3.xml
@@ -0,0 +1,5 @@
+<design>
+
+<package name="recursion" package="mod.recursion3" subpackages="include"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/returnvaldepend.xml b/test/resources/design/designfiles/returnvaldepend.xml
new file mode 100644
index 0000000..d1abdab
--- /dev/null
+++ b/test/resources/design/designfiles/returnvaldepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.returnvaldepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/signatureexceptiondepend.xml b/test/resources/design/designfiles/signatureexceptiondepend.xml
new file mode 100644
index 0000000..446333e
--- /dev/null
+++ b/test/resources/design/designfiles/signatureexceptiondepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.signatureexceptiondepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/staticdepend.xml b/test/resources/design/designfiles/staticdepend.xml
new file mode 100644
index 0000000..94e41c8
--- /dev/null
+++ b/test/resources/design/designfiles/staticdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.staticdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/staticfield2depend.xml b/test/resources/design/designfiles/staticfield2depend.xml
new file mode 100644
index 0000000..69a1e4f
--- /dev/null
+++ b/test/resources/design/designfiles/staticfield2depend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.staticfield2depend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/staticfielddepend.xml b/test/resources/design/designfiles/staticfielddepend.xml
new file mode 100644
index 0000000..d477496
--- /dev/null
+++ b/test/resources/design/designfiles/staticfielddepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.staticfielddepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/staticfinaldepend.xml b/test/resources/design/designfiles/staticfinaldepend.xml
new file mode 100644
index 0000000..a264547
--- /dev/null
+++ b/test/resources/design/designfiles/staticfinaldepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.staticfinaldepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/superdepend.xml b/test/resources/design/designfiles/superdepend.xml
new file mode 100644
index 0000000..153ee2b
--- /dev/null
+++ b/test/resources/design/designfiles/superdepend.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.superdepend"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/warfailure.xml b/test/resources/design/designfiles/warfailure.xml
new file mode 100644
index 0000000..daf5368
--- /dev/null
+++ b/test/resources/design/designfiles/warfailure.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.warfailure"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/designfiles/warsuccess.xml b/test/resources/design/designfiles/warsuccess.xml
new file mode 100644
index 0000000..3e100e9
--- /dev/null
+++ b/test/resources/design/designfiles/warsuccess.xml
@@ -0,0 +1,6 @@
+<design>
+
+<package name="dummy" package="mod.dummy"/>
+<package name="client" package="mod.warsuccess" depends="dummy"/>
+
+</design> \ No newline at end of file
diff --git a/test/resources/design/src/mod/arraydepend/ClassDependsOnArray.java b/test/resources/design/src/mod/arraydepend/ClassDependsOnArray.java
new file mode 100644
index 0000000..ed4b01c
--- /dev/null
+++ b/test/resources/design/src/mod/arraydepend/ClassDependsOnArray.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.arraydepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnArray {
+
+ public void something() {
+ Object[] o = new DummyClass[5];
+ }
+}
diff --git a/test/resources/design/src/mod/arraydepend2/ClassDependsOnArray.java b/test/resources/design/src/mod/arraydepend2/ClassDependsOnArray.java
new file mode 100644
index 0000000..4d65a7a
--- /dev/null
+++ b/test/resources/design/src/mod/arraydepend2/ClassDependsOnArray.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.arraydepend2;
+
+
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnArray {
+
+ public void testArray() throws Exception {
+ Class c = String[].class;
+ }
+}
diff --git a/test/resources/design/src/mod/arraydepend3/ClassDependsOnArray.java b/test/resources/design/src/mod/arraydepend3/ClassDependsOnArray.java
new file mode 100644
index 0000000..2ff6d67
--- /dev/null
+++ b/test/resources/design/src/mod/arraydepend3/ClassDependsOnArray.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.arraydepend3;
+
+import mod.dummy.DummyClass;
+
+
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnArray {
+
+ public void testArray() throws Exception {
+ Class c = DummyClass[].class;
+ }
+}
diff --git a/test/resources/design/src/mod/castdepend/ClassDependsOnCast.java b/test/resources/design/src/mod/castdepend/ClassDependsOnCast.java
new file mode 100644
index 0000000..b6ad33a
--- /dev/null
+++ b/test/resources/design/src/mod/castdepend/ClassDependsOnCast.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.castdepend;
+
+import mod.dummy.DummyInterface;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnCast {
+
+ public void getSomething(Object obj) {
+ Object o = (DummyInterface)obj;
+ }
+}
diff --git a/test/resources/design/src/mod/catchdepend/ClassDependsOnCatch.java b/test/resources/design/src/mod/catchdepend/ClassDependsOnCatch.java
new file mode 100644
index 0000000..a103240
--- /dev/null
+++ b/test/resources/design/src/mod/catchdepend/ClassDependsOnCatch.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.catchdepend;
+
+import mod.dummy.DummyRuntimeException;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnCatch {
+
+ public void doNothing() {
+ try {
+ int x = 0;
+ int y = x+4;
+ } catch(DummyRuntimeException e) {
+
+ }
+ }
+}
diff --git a/test/resources/design/src/mod/declarejavautil/ClassDependsOnJavaUtil.java b/test/resources/design/src/mod/declarejavautil/ClassDependsOnJavaUtil.java
new file mode 100644
index 0000000..077da65
--- /dev/null
+++ b/test/resources/design/src/mod/declarejavautil/ClassDependsOnJavaUtil.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 19, 2005
+ */
+package mod.declarejavautil;
+
+import java.util.List;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnJavaUtil {
+
+ public List list;
+}
diff --git a/test/resources/design/src/mod/declarejavax/ClassDependsOnJavax.java b/test/resources/design/src/mod/declarejavax/ClassDependsOnJavax.java
new file mode 100644
index 0000000..cd79675
--- /dev/null
+++ b/test/resources/design/src/mod/declarejavax/ClassDependsOnJavax.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 19, 2005
+ */
+package mod.declarejavax;
+
+import javax.swing.JButton;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnJavax {
+
+ public JButton b = null;
+
+}
diff --git a/test/resources/design/src/mod/dummy/DummyClass.java b/test/resources/design/src/mod/dummy/DummyClass.java
new file mode 100644
index 0000000..f2f48df
--- /dev/null
+++ b/test/resources/design/src/mod/dummy/DummyClass.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.dummy;
+
+/**
+ *
+ * @author dhiller
+ */
+public class DummyClass {
+
+ public static final String CONSTANT = "asdf";
+ public static String staticField = "xxxx";
+
+ public static String returnSomething() {
+ return "Xxx";
+ }
+}
diff --git a/test/resources/design/src/mod/dummy/DummyException.java b/test/resources/design/src/mod/dummy/DummyException.java
new file mode 100644
index 0000000..3884fc1
--- /dev/null
+++ b/test/resources/design/src/mod/dummy/DummyException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.dummy;
+
+/**
+ *
+ * @author dhiller
+ */
+public class DummyException extends Exception {
+
+}
diff --git a/test/resources/design/src/mod/dummy/DummyInterface.java b/test/resources/design/src/mod/dummy/DummyInterface.java
new file mode 100644
index 0000000..e7432fa
--- /dev/null
+++ b/test/resources/design/src/mod/dummy/DummyInterface.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.dummy;
+
+/**
+ *
+ * @author dhiller
+ */
+public interface DummyInterface {
+
+}
diff --git a/test/resources/design/src/mod/dummy/DummyRuntimeException.java b/test/resources/design/src/mod/dummy/DummyRuntimeException.java
new file mode 100644
index 0000000..53cb35a
--- /dev/null
+++ b/test/resources/design/src/mod/dummy/DummyRuntimeException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.dummy;
+
+/**
+ *
+ * @author dhiller
+ */
+public class DummyRuntimeException extends RuntimeException {
+
+}
diff --git a/test/resources/design/src/mod/fielddepend/ClassDependsOnField.java b/test/resources/design/src/mod/fielddepend/ClassDependsOnField.java
new file mode 100644
index 0000000..226003b
--- /dev/null
+++ b/test/resources/design/src/mod/fielddepend/ClassDependsOnField.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.fielddepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ * This class depends on a field in another package.
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnField {
+
+ private DummyClass f;
+}
diff --git a/test/resources/design/src/mod/fieldrefdepend/ClassDependsOnReferenceInFieldDeclaration.java b/test/resources/design/src/mod/fieldrefdepend/ClassDependsOnReferenceInFieldDeclaration.java
new file mode 100644
index 0000000..8329bfc
--- /dev/null
+++ b/test/resources/design/src/mod/fieldrefdepend/ClassDependsOnReferenceInFieldDeclaration.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.fieldrefdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnReferenceInFieldDeclaration {
+
+ private Class c = DummyClass.class;
+
+}
diff --git a/test/resources/design/src/mod/innerclassdepend/InnerClassDependsOnSuper.java b/test/resources/design/src/mod/innerclassdepend/InnerClassDependsOnSuper.java
new file mode 100644
index 0000000..ee882e5
--- /dev/null
+++ b/test/resources/design/src/mod/innerclassdepend/InnerClassDependsOnSuper.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.innerclassdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class InnerClassDependsOnSuper {
+
+ private class Inner extends DummyClass {
+
+ }
+}
diff --git a/test/resources/design/src/mod/instanceofdepend/ClassDependsOnInstanceOf.java b/test/resources/design/src/mod/instanceofdepend/ClassDependsOnInstanceOf.java
new file mode 100644
index 0000000..55a78bb
--- /dev/null
+++ b/test/resources/design/src/mod/instanceofdepend/ClassDependsOnInstanceOf.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.instanceofdepend;
+
+import mod.dummy.DummyInterface;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnInstanceOf {
+
+ public void getSomething(Object o) {
+ int x = 0;
+ if(o instanceof DummyInterface) {
+ x = 4;
+ }
+ }
+}
diff --git a/test/resources/design/src/mod/interfacedepend/ClassDependsOnInterfaceMod2.java b/test/resources/design/src/mod/interfacedepend/ClassDependsOnInterfaceMod2.java
new file mode 100644
index 0000000..6713b1c
--- /dev/null
+++ b/test/resources/design/src/mod/interfacedepend/ClassDependsOnInterfaceMod2.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.interfacedepend;
+
+import mod.dummy.DummyInterface;
+
+/**
+ * This class depends on an interface in another package creating a dependency
+ * between packages.
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnInterfaceMod2 implements DummyInterface {
+
+}
diff --git a/test/resources/design/src/mod/localvardepend/ClassDependsOnLocalVar.java b/test/resources/design/src/mod/localvardepend/ClassDependsOnLocalVar.java
new file mode 100644
index 0000000..cd177da
--- /dev/null
+++ b/test/resources/design/src/mod/localvardepend/ClassDependsOnLocalVar.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.localvardepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnLocalVar {
+
+ public String doNothing() {
+ DummyClass c = null;
+
+ return ""+c;
+ }
+}
diff --git a/test/resources/design/src/mod/localvarrefdepend/ClassDependsOnLocalVariableReference.java b/test/resources/design/src/mod/localvarrefdepend/ClassDependsOnLocalVariableReference.java
new file mode 100644
index 0000000..8e77433
--- /dev/null
+++ b/test/resources/design/src/mod/localvarrefdepend/ClassDependsOnLocalVariableReference.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.localvarrefdepend;
+
+import mod.dummy.DummyInterface;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnLocalVariableReference {
+
+ public void doNothing() {
+ Class c = DummyInterface.class;
+ }
+}
diff --git a/test/resources/design/src/mod/newdepend/ClassDependsOnNew.java b/test/resources/design/src/mod/newdepend/ClassDependsOnNew.java
new file mode 100644
index 0000000..efcaa49
--- /dev/null
+++ b/test/resources/design/src/mod/newdepend/ClassDependsOnNew.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.newdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnNew {
+
+ public void doNothing() {
+ new DummyClass();
+ }
+}
diff --git a/test/resources/design/src/mod/newdepend2/ClassDependsOnNewInField.java b/test/resources/design/src/mod/newdepend2/ClassDependsOnNewInField.java
new file mode 100644
index 0000000..d76ade3
--- /dev/null
+++ b/test/resources/design/src/mod/newdepend2/ClassDependsOnNewInField.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.newdepend2;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnNewInField {
+
+ public Object o = new DummyClass();
+}
diff --git a/test/resources/design/src/mod/nodebugoption/ClassDependsOnLocalVar.java b/test/resources/design/src/mod/nodebugoption/ClassDependsOnLocalVar.java
new file mode 100644
index 0000000..bb65e63
--- /dev/null
+++ b/test/resources/design/src/mod/nodebugoption/ClassDependsOnLocalVar.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.nodebugoption;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnLocalVar {
+
+ public void doSomething() {
+ DummyClass c = null;
+ //without debug option enabled, the type DummyClass is lost so we
+ //must fail with the error saying class wasn't compiled with -g option
+ //enabled in javac.
+ }
+}
diff --git a/test/resources/design/src/mod/paramdepend/ClassDependsOnParameter.java b/test/resources/design/src/mod/paramdepend/ClassDependsOnParameter.java
new file mode 100644
index 0000000..12866b1
--- /dev/null
+++ b/test/resources/design/src/mod/paramdepend/ClassDependsOnParameter.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.paramdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnParameter {
+
+ public void setSomething(String dummy, DummyClass c) {
+
+ }
+}
diff --git a/test/resources/design/src/mod/passlocaldepend/ClassDependsOnClassInSamePackage.java b/test/resources/design/src/mod/passlocaldepend/ClassDependsOnClassInSamePackage.java
new file mode 100644
index 0000000..a2ae720
--- /dev/null
+++ b/test/resources/design/src/mod/passlocaldepend/ClassDependsOnClassInSamePackage.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.passlocaldepend;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnClassInSamePackage {
+
+ public void doSomething(FakeClass c) {
+
+ }
+}
diff --git a/test/resources/design/src/mod/passlocaldepend/FakeClass.java b/test/resources/design/src/mod/passlocaldepend/FakeClass.java
new file mode 100644
index 0000000..ed35025
--- /dev/null
+++ b/test/resources/design/src/mod/passlocaldepend/FakeClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.passlocaldepend;
+
+/**
+ *
+ * @author dhiller
+ */
+public class FakeClass {
+
+}
diff --git a/test/resources/design/src/mod/putstatic/ClassDependsOnNothing.java b/test/resources/design/src/mod/putstatic/ClassDependsOnNothing.java
new file mode 100644
index 0000000..fbedddf
--- /dev/null
+++ b/test/resources/design/src/mod/putstatic/ClassDependsOnNothing.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.putstatic;
+
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnNothing {
+
+ private static String s;
+ public static void setJarLocator(String l) {
+ s = l;
+ }
+}
diff --git a/test/resources/design/src/mod/recursion/client/ClassDependsOnSubPackage.java b/test/resources/design/src/mod/recursion/client/ClassDependsOnSubPackage.java
new file mode 100644
index 0000000..ce95d9c
--- /dev/null
+++ b/test/resources/design/src/mod/recursion/client/ClassDependsOnSubPackage.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.recursion.client;
+
+import mod.recursion.rec.a.FakeClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnSubPackage {
+
+ public FakeClass getSoemthing() {
+ return null;
+ }
+}
diff --git a/test/resources/design/src/mod/recursion/rec/a/FakeClass.java b/test/resources/design/src/mod/recursion/rec/a/FakeClass.java
new file mode 100644
index 0000000..ada6615
--- /dev/null
+++ b/test/resources/design/src/mod/recursion/rec/a/FakeClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.recursion.rec.a;
+
+/**
+ *
+ * @author dhiller
+ */
+public class FakeClass {
+
+}
diff --git a/test/resources/design/src/mod/recursion2/dependency/Dependency.java b/test/resources/design/src/mod/recursion2/dependency/Dependency.java
new file mode 100644
index 0000000..dc9b594
--- /dev/null
+++ b/test/resources/design/src/mod/recursion2/dependency/Dependency.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.recursion2.dependency;
+
+/**
+ *
+ * @author dhiller
+ */
+public class Dependency {
+
+}
diff --git a/test/resources/design/src/mod/recursion2/rec/client/SubpackageClassDependsOnPackage.java b/test/resources/design/src/mod/recursion2/rec/client/SubpackageClassDependsOnPackage.java
new file mode 100644
index 0000000..57dc96a
--- /dev/null
+++ b/test/resources/design/src/mod/recursion2/rec/client/SubpackageClassDependsOnPackage.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 16, 2005
+ */
+package mod.recursion2.rec.client;
+
+import mod.recursion2.dependency.Dependency;
+
+/**
+ *
+ * @author dhiller
+ */
+public class SubpackageClassDependsOnPackage {
+
+ public Dependency doNothing() {
+ return null;
+ }
+}
diff --git a/test/resources/design/src/mod/recursion3/client/SubpackageClassDependsOnSubpackage.java b/test/resources/design/src/mod/recursion3/client/SubpackageClassDependsOnSubpackage.java
new file mode 100644
index 0000000..64dd1ce
--- /dev/null
+++ b/test/resources/design/src/mod/recursion3/client/SubpackageClassDependsOnSubpackage.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 16, 2005
+ */
+package mod.recursion3.client;
+
+import mod.recursion3.svc.DependencyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class SubpackageClassDependsOnSubpackage {
+
+ public void doSomething(DependencyClass c) {
+
+ }
+}
diff --git a/test/resources/design/src/mod/recursion3/svc/DependencyClass.java b/test/resources/design/src/mod/recursion3/svc/DependencyClass.java
new file mode 100644
index 0000000..e3bc462
--- /dev/null
+++ b/test/resources/design/src/mod/recursion3/svc/DependencyClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 16, 2005
+ */
+package mod.recursion3.svc;
+
+/**
+ *
+ * @author dhiller
+ */
+public class DependencyClass {
+
+}
diff --git a/test/resources/design/src/mod/returnvaldepend/ClassDependsOnReturnValue.java b/test/resources/design/src/mod/returnvaldepend/ClassDependsOnReturnValue.java
new file mode 100644
index 0000000..61f00ae
--- /dev/null
+++ b/test/resources/design/src/mod/returnvaldepend/ClassDependsOnReturnValue.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.returnvaldepend;
+
+import mod.dummy.DummyInterface;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnReturnValue {
+
+ public DummyInterface getSomething() {
+ return null;
+ }
+}
diff --git a/test/resources/design/src/mod/signatureexceptiondepend/ClassDependsOnExceptionInMethodSignature.java b/test/resources/design/src/mod/signatureexceptiondepend/ClassDependsOnExceptionInMethodSignature.java
new file mode 100644
index 0000000..a235e12
--- /dev/null
+++ b/test/resources/design/src/mod/signatureexceptiondepend/ClassDependsOnExceptionInMethodSignature.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.signatureexceptiondepend;
+
+import mod.dummy.DummyException;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnExceptionInMethodSignature {
+
+ public String doNothing() throws DummyException {
+ return null;
+ }
+}
diff --git a/test/resources/design/src/mod/staticdepend/ClassDependsOnStatic.java b/test/resources/design/src/mod/staticdepend/ClassDependsOnStatic.java
new file mode 100644
index 0000000..60b1f53
--- /dev/null
+++ b/test/resources/design/src/mod/staticdepend/ClassDependsOnStatic.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.staticdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnStatic {
+
+ public String getSomething() {
+ return DummyClass.returnSomething();
+ }
+}
diff --git a/test/resources/design/src/mod/staticfield2depend/ClassDependsOnStaticField.java b/test/resources/design/src/mod/staticfield2depend/ClassDependsOnStaticField.java
new file mode 100644
index 0000000..6d2a587
--- /dev/null
+++ b/test/resources/design/src/mod/staticfield2depend/ClassDependsOnStaticField.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.staticfield2depend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnStaticField {
+
+ public static DummyClass x = null;
+
+
+}
diff --git a/test/resources/design/src/mod/staticfielddepend/ClassDependsOnStaticField.java b/test/resources/design/src/mod/staticfielddepend/ClassDependsOnStaticField.java
new file mode 100644
index 0000000..67f35db
--- /dev/null
+++ b/test/resources/design/src/mod/staticfielddepend/ClassDependsOnStaticField.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.staticfielddepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnStaticField {
+
+ public void doNothing() {
+ String s = DummyClass.staticField;
+ }
+}
diff --git a/test/resources/design/src/mod/staticfinaldepend/ClassDependsOnConstant.java b/test/resources/design/src/mod/staticfinaldepend/ClassDependsOnConstant.java
new file mode 100644
index 0000000..6273c9a
--- /dev/null
+++ b/test/resources/design/src/mod/staticfinaldepend/ClassDependsOnConstant.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 9, 2005
+ */
+package mod.staticfinaldepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class ClassDependsOnConstant {
+
+ public void doNothing() {
+ String s = ""+DummyClass.CONSTANT;
+ }
+}
diff --git a/test/resources/design/src/mod/superdepend/ClassDependsOnSuperMod2.java b/test/resources/design/src/mod/superdepend/ClassDependsOnSuperMod2.java
new file mode 100644
index 0000000..880f757
--- /dev/null
+++ b/test/resources/design/src/mod/superdepend/ClassDependsOnSuperMod2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.superdepend;
+
+import mod.dummy.DummyClass;
+
+/**
+ * This class depends on a superclass in another package creating a dependency
+ * between packages.
+ * @author dhiller
+ */
+public class ClassDependsOnSuperMod2 extends DummyClass {
+
+}
diff --git a/test/resources/design/src/mod/temp/Factory.java b/test/resources/design/src/mod/temp/Factory.java
new file mode 100644
index 0000000..a05622e
--- /dev/null
+++ b/test/resources/design/src/mod/temp/Factory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Jan 13, 2005
+ */
+package mod.temp;
+
+import mod.dummy.DummyClass;
+
+/**
+ *
+ * @author dhiller
+ */
+public class Factory {
+
+ public static DummyClass create() {
+ return new DummyClass();
+ }
+}
diff --git a/test/resources/design/src/mod/warfailure/ClassDependsOnSuperMod2.java b/test/resources/design/src/mod/warfailure/ClassDependsOnSuperMod2.java
new file mode 100644
index 0000000..3ee27c7
--- /dev/null
+++ b/test/resources/design/src/mod/warfailure/ClassDependsOnSuperMod2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.warfailure;
+
+import mod.dummy.DummyClass;
+
+/**
+ * This class depends on a superclass in another package creating a dependency
+ * between packages.
+ * @author dhiller
+ */
+public class ClassDependsOnSuperMod2 extends DummyClass {
+
+}
diff --git a/test/resources/design/src/mod/warsuccess/ClassDependsOnSuperMod2.java b/test/resources/design/src/mod/warsuccess/ClassDependsOnSuperMod2.java
new file mode 100644
index 0000000..da5e8a2
--- /dev/null
+++ b/test/resources/design/src/mod/warsuccess/ClassDependsOnSuperMod2.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Created on Dec 29, 2004
+ */
+package mod.warsuccess;
+
+import mod.dummy.DummyClass;
+
+/**
+ * This class depends on a superclass in another package creating a dependency
+ * between packages.
+ * @author dhiller
+ */
+public class ClassDependsOnSuperMod2 extends DummyClass {
+
+}
diff --git a/test/resources/design/verifydesign.xml b/test/resources/design/verifydesign.xml
new file mode 100644
index 0000000..53d7d17
--- /dev/null
+++ b/test/resources/design/verifydesign.xml
@@ -0,0 +1,440 @@
+<project name="test_verifydesign" basedir="." default="cleanup">
+ <property name="output" value="build"/>
+ <property name="classes" value="${output}/classes"/>
+ <property name="jardir" value="${output}/jar"/>
+ <property name="jar" value="${jardir}/test.jar"/>
+ <property name="war" value="${jardir}/test.war"/>
+ <property name="src" value="src"/>
+ <property name="mod" value="mod"/>
+ <property name="dummy" value="dummy"/>
+ <property name="designs" value="designfiles"/>
+ <property name="webxml" value="web.xml"/>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="cleanup">
+ <delete quiet="yes" dir="${output}"/>
+ </target>
+
+ <target name="init">
+ <mkdir dir="${jardir}"/>
+ </target>
+
+ <target name="templateTest">
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${dummy}/**"/>
+ <include name="${mod}/${package.under.test}/**"/>
+ </javac>
+ <jar destfile="${jar}" basedir="${classes}"/>
+ </target>
+
+ <target name="templateWar">
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${dummy}/**"/>
+ <include name="${mod}/${package.under.test}/**"/>
+ </javac>
+
+ <war destfile="${war}" webxml="${webxml}">
+ <classes dir="${classes}"/>
+ </war>
+ </target>
+
+ <target name="testArrayDepend" depends="init">
+ <property name="package" value="arraydepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testArrayDepend2" depends="init">
+ <property name="package" value="arraydepend2"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testArrayDepend3" depends="init">
+ <property name="package" value="arraydepend3"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testBadXML" depends="init">
+ <property name="package" value="badxml"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testCastDepend" depends="init">
+ <property name="package" value="castdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testCatchDepend" depends="init">
+ <property name="package" value="catchdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testClassFiles" depends="init">
+ <property name="package" value="castdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign design="${designs}/${package}.xml">
+ <path>
+ <fileset dir="${classes}">
+ <include name="**/*.class"/>
+ </fileset>
+ </path>
+ </verifydesign>
+ </target>
+
+ <target name="testDeclareJavaUtil" depends="init">
+ <property name="package" value="declarejavautil"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testDeclareJavaUtilFail" depends="init">
+ <property name="package" value="declarejavautil"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}fail.xml"/>
+ </target>
+
+ <target name="testDeclareJavax" depends="init">
+ <property name="package" value="declarejavax"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testDeclareJavaxPass" depends="init">
+ <property name="package" value="declarejavax"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}pass.xml"/>
+ </target>
+
+ <target name="testFieldDepend" depends="init">
+ <property name="package" value="fielddepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testFieldRefDepend" depends="init">
+ <property name="package" value="fieldrefdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testInnerClassDepend" depends="init">
+ <property name="package" value="innerclassdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testInstanceOfDepend" depends="init">
+ <property name="package" value="instanceofdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testInterfaceDepend" depends="init">
+ <property name="package" value="interfacedepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testLocalVarDepend" depends="init">
+ <property name="package" value="localvardepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testLocalVarRefDepend" depends="init">
+ <property name="package" value="localvarrefdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testMissingAttribute" depends="init">
+ <property name="package" value="missingattribute"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testMultipleErrors" depends="init">
+ <property name="package" value="multipleerrors"/>
+
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${dummy}/**"/>
+ <include name="${mod}/arraydepend/**"/>
+ <include name="${mod}/castdepend/**"/>
+ <include name="${mod}/catchdepend/**"/>
+ </javac>
+ <jar destfile="${jar}" basedir="${classes}"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testNewDepend" depends="init">
+ <property name="package" value="newdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testNewDepend2" depends="init">
+ <property name="package" value="newdepend2"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testNoDebugOption" depends="init">
+ <property name="package" value="nodebugoption"/>
+
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${dummy}/**"/>
+ </javac>
+ <javac srcdir="${src}" debug="false" destdir="${classes}">
+ <include name="${mod}/${package}/**"/>
+ </javac>
+
+ <jar destfile="${jar}" basedir="${classes}"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testNoJar" depends="init">
+ <property name="package" value="nojar"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testParamDepend" depends="init">
+ <property name="package" value="paramdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testPassLocalDepend" depends="init">
+ <property name="package" value="passlocaldepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testPathElementLocation" depends="init">
+ <property name="package" value="putstatic"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign design="${designs}/${package}.xml">
+ <path>
+ <pathelement location="${classes}"/>
+ </path>
+ </verifydesign>
+ </target>
+
+ <target name="testPathElementPath" depends="init">
+ <property name="package" value="pathelementpath"/>
+ <property name="classes2" value="${output}/classes2"/>
+ <property name="classes3" value="${output}/classes3"/>
+ <mkdir dir="${classes}"/>
+ <mkdir dir="${classes2}"/>
+ <mkdir dir="${classes3}"/>
+
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${dummy}/**"/>
+ </javac>
+
+ <javac srcdir="${src}" debug="true" destdir="${classes2}" classpath="${classes}">
+ <include name="${mod}/putstatic/**"/>
+ </javac>
+
+ <javac srcdir="${src}" debug="true" destdir="${classes3}" classpath="${classes}">
+ <include name="${mod}/arraydepend2/**"/>
+ </javac>
+
+ <jar destfile="${jar}" basedir="${classes3}"/>
+
+ <verifydesign design="${designs}/${package}.xml">
+ <path>
+ <pathelement path="${classes2}:${jar}:${classes}"/>
+ </path>
+ </verifydesign>
+ </target>
+
+ <target name="testPutStatic" depends="init">
+ <property name="package" value="putstatic"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testRecursion" depends="init">
+ <property name="package" value="recursion"/>
+
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${package}/**"/>
+ </javac>
+
+ <jar destfile="${jar}" basedir="${classes}"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testRecursion2" depends="init">
+ <property name="package" value="recursion2"/>
+
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${package}/**"/>
+ </javac>
+
+ <jar destfile="${jar}" basedir="${classes}"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testRecursion3" depends="init">
+ <property name="package" value="recursion3"/>
+
+ <delete dir="${classes}"/>
+ <mkdir dir="${classes}"/>
+ <javac srcdir="${src}" debug="true" destdir="${classes}">
+ <include name="${mod}/${package}/**"/>
+ </javac>
+
+ <jar destfile="${jar}" basedir="${classes}"/>
+
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testReturnValDepend" depends="init">
+ <property name="package" value="returnvaldepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testSignatureExceptionDepend" depends="init">
+ <property name="package" value="signatureexceptiondepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testStaticDepend" depends="init">
+ <property name="package" value="staticdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testStaticField2Depend" depends="init">
+ <property name="package" value="staticfield2depend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testStaticFieldDepend" depends="init">
+ <property name="package" value="staticfielddepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testStaticFinalDepend" depends="init">
+ <property name="package" value="staticfinaldepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testSuperDepend" depends="init">
+ <property name="package" value="superdepend"/>
+ <antcall target="templateTest">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${jar}" design="${designs}/${package}.xml"
+ deletefiles="true"/>
+ </target>
+
+ <target name="testWarSuccess" depends="init">
+ <property name="package" value="warsuccess"/>
+ <antcall target="templateWar">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${war}" design="${designs}/${package}.xml"/>
+ </target>
+
+ <target name="testWarFailure" depends="init">
+ <property name="package" value="warfailure"/>
+ <antcall target="templateWar">
+ <param name="package.under.test" value="${package}"/>
+ </antcall>
+ <verifydesign jar="${war}" design="${designs}/${package}.xml"/>
+ </target>
+</project>
diff --git a/test/resources/design/web.xml b/test/resources/design/web.xml
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/resources/design/web.xml
diff --git a/test/resources/logic/antcallbacktest.xml b/test/resources/logic/antcallbacktest.xml
new file mode 100644
index 0000000..7f165c8
--- /dev/null
+++ b/test/resources/logic/antcallbacktest.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+
+<project name="antcallbacktest" basedir="." default="test1">
+ <description>
+ test build file for the AntCallBack task
+ </description>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+
+ <target name="test1">
+ <antcallback target="setProperty" return="prop1"/>
+ </target>
+
+ <target name="test2">
+ <antcallback target="setProperties" return="prop1,prop2,prop3"/>
+ </target>
+
+ <target name="test3">
+ <antcallback target="setProperties" return="prop1, prop2, prop3"/>
+ </target>
+
+ <target name="test4">
+ <antcallback target="setTwoProperties" return="prop1, prop2, prop3"/>
+ </target>
+
+ <target name="test5">
+ <!-- the beauty of unit testing is this test for checking that a property
+ won't get overwritten also revealed that params weren't supported.
+ AntCallBack is actually based on the ant task, not antcall. -->
+ <antcallback target="setProperties" return="prop1, prop2, prop3">
+ <param name="prop1" value="blah"/>
+ </antcallback>
+ </target>
+
+ <target name="setProperty">
+ <property name="prop1" value="prop1"/>
+ </target>
+
+ <target name="setTwoProperties">
+ <property name="prop2" value="prop2"/>
+ <property name="prop3" value="prop3"/>
+ </target>
+
+ <target name="setProperties">
+ <property name="prop1" value="prop1"/>
+ <property name="prop2" value="prop2"/>
+ <property name="prop3" value="prop3"/>
+ </target>
+
+ <target name="setNoProperties"/>
+</project>
diff --git a/test/resources/logic/asserttest.xml b/test/resources/logic/asserttest.xml
new file mode 100644
index 0000000..2e920e2
--- /dev/null
+++ b/test/resources/logic/asserttest.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+
+<project name="asserttest" basedir="." default="test1">
+ <description>
+ test build file for the Assert task
+ </description>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ <property name="ant.enable.asserts" value="true"/>
+
+ <target name="test1">
+ <property name="testprop" value="true"/>
+ <assert name="testprop"/>
+ <assert name="testprop" value="true"/>
+ </target>
+
+ <target name="test2">
+ <assert name="testprop"/>
+ </target>
+
+ <target name="test3">
+ <property name="testprop" value="true"/>
+ <assert name="testprop" value="12"/>
+ </target>
+
+ <!-- test boolean conditions -->
+ <target name="test4">
+ <assert>
+ <bool>
+ <isgreaterthan arg1="6.02" arg2="4"/>
+ </bool>
+ </assert>
+ <assert>
+ <bool>
+ <isgreaterthan arg1="Many" arg2="Less"/>
+ </bool>
+ </assert>
+ </target>
+ <target name="test5">
+ <assert>
+ <bool>
+ <islessthan arg1="6.02" arg2="23.456"/>
+ </bool>
+ </assert>
+ <assert>
+ <bool>
+ <islessthan arg1="least" arg2="most"/>
+ </bool>
+ </assert>
+ </target>
+ <target name="test6">
+ <property name="testprop" value="false"/>
+ <assert>
+ <bool>
+ <ispropertyfalse property="testprop"/>
+ </bool>
+ </assert>
+ </target>
+ <target name="test7">
+ <property name="testprop" value="no"/>
+ <assert>
+ <bool>
+ <ispropertytrue property="testprop"/>
+ </bool>
+ </assert>
+ </target>
+ <target name="test8">
+ <property name="testprop" value="yes"/>
+ <assert>
+ <bool>
+ <ispropertytrue property="testprop"/>
+ </bool>
+ </assert>
+ </target>
+ <target name="test9">
+ <property name="testprop" value="on"/>
+ <assert>
+ <bool>
+ <ispropertyfalse property="testprop"/>
+ </bool>
+ </assert>
+ </target>
+
+</project>
diff --git a/test/resources/logic/foreach.xml b/test/resources/logic/foreach.xml
new file mode 100644
index 0000000..00e8c8a
--- /dev/null
+++ b/test/resources/logic/foreach.xml
@@ -0,0 +1,104 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="teardown">
+ <delete dir="foreachtest"/>
+ </target>
+
+ <target name="echo">
+ <echo>Called with param: ${param}</echo>
+ </target>
+
+ <target name="convert-bar" unless="param">
+ <property name="param" refid="bar"/>
+ </target>
+
+ <target name="echoFilename" depends="convert-bar">
+ <basename file="${param}" property="param2"/>
+ <echo>Called with param: ${param2}</echo>
+ </target>
+
+ <target name="simpleList" depends="setup">
+ <foreach list="1,2,3" target="echo" param="param"/>
+ </target>
+
+ <target name="delimiter" depends="setup">
+ <foreach list="1/2/3" target="echo" param="param" delimiter="/"/>
+ </target>
+
+ <target name="fileset" depends="setup">
+ <mkdir dir="foreachtest"/>
+ <touch file="foreachtest/1"/>
+ <touch file="foreachtest/2"/>
+ <touch file="foreachtest/3"/>
+ <foreach target="echoFilename" param="param">
+ <fileset dir="foreachtest"/>
+ </foreach>
+ </target>
+
+ <target name="filesetAndList" depends="setup">
+ <mkdir dir="foreachtest"/>
+ <touch file="foreachtest/3"/>
+ <foreach list="1,2" target="echoFilename" param="param">
+ <fileset dir="foreachtest"/>
+ </foreach>
+ </target>
+
+ <target name="noList" depends="setup">
+ <foreach target="echo" param="param"/>
+ </target>
+
+ <target name="noTarget" depends="setup">
+ <foreach list="1,2,3" param="param"/>
+ </target>
+
+ <target name="noParam" depends="setup">
+ <foreach list="1,2,3" target="echo"/>
+ </target>
+
+ <target name="nestedParam" depends="setup">
+ <foreach list="1" target="echo" param="who-cares">
+ <param name="param" value="rincewind"/>
+ </foreach>
+ </target>
+
+ <target name="nestedReference" depends="setup">
+ <path id="foo">
+ <pathelement location="twoflower"/>
+ </path>
+ <foreach list="1" target="echoFilename" param="who-cares">
+ <reference refid="foo" torefid="bar"/>
+ </foreach>
+ </target>
+
+ <target name="path" depends="setup">
+ <mkdir dir="foreachtest"/>
+ <touch file="foreachtest/1"/>
+ <touch file="foreachtest/2"/>
+ <touch file="foreachtest/3"/>
+ <foreach target="echoFilename" param="param">
+ <path>
+ <fileset dir="foreachtest"/>
+ </path>
+ </foreach>
+ </target>
+
+ <target name="pathAndList" depends="setup">
+ <mkdir dir="foreachtest"/>
+ <touch file="foreachtest/3"/>
+ <foreach list="1,2" target="echoFilename" param="param">
+ <path>
+ <fileset dir="foreachtest"/>
+ </path>
+ </foreach>
+ </target>
+
+</project> \ No newline at end of file
diff --git a/test/resources/logic/if.xml b/test/resources/logic/if.xml
new file mode 100644
index 0000000..f9c23c4
--- /dev/null
+++ b/test/resources/logic/if.xml
@@ -0,0 +1,146 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="noCondition" depends="setup">
+ <if>
+ <then>
+ <echo>Foo</echo>
+ </then>
+ </if>
+ </target>
+
+ <target name="twoConditions" depends="setup">
+ <if>
+ <isset property="1"/>
+ <isset property="2"/>
+ <then>
+ <echo>Foo</echo>
+ </then>
+ </if>
+ </target>
+
+ <target name="nothingToDo" depends="setup">
+ <if>
+ <isset property="antcontrib.jar"/>
+ </if>
+ </target>
+
+ <target name="twoThens" depends="setup">
+ <if>
+ <isset property="antcontrib.jar"/>
+ <then/>
+ <then/>
+ </if>
+ </target>
+
+ <target name="twoElses" depends="setup">
+ <if>
+ <isset property="antcontrib.jar"/>
+ <else/>
+ <else/>
+ </if>
+ </target>
+
+ <target name="normalOperation" depends="setup">
+ <if>
+ <isset property="antcontrib.jar"/>
+ <then>
+ <echo>In then</echo>
+ <property name="inner" value="some value"/>
+ <echo>${inner}</echo>
+ </then>
+ <else>
+ <echo>In else</echo>
+ </else>
+ </if>
+ </target>
+
+ <target name="normalOperation2" depends="setup">
+ <if>
+ <not>
+ <isset property="antcontrib.jar"/>
+ </not>
+ <then>
+ <echo>In then</echo>
+ </then>
+ <else>
+ <echo>In else</echo>
+ </else>
+ </if>
+ </target>
+
+ <target name="noConditionInElseif" depends="setup">
+ <if>
+ <isset property="1"/>
+ <elseif>
+ <then>
+ <echo>Foo</echo>
+ </then>
+ </elseif>
+ </if>
+ </target>
+
+ <target name="twoConditionsInElseif" depends="setup">
+ <if>
+ <isset property="1"/>
+ <elseif>
+ <isset property="1"/>
+ <isset property="2"/>
+ <then>
+ <echo>Foo</echo>
+ </then>
+ </elseif>
+ </if>
+ </target>
+
+ <target name="normalOperationElseif" depends="setup">
+ <if>
+ <not>
+ <isset property="antcontrib.jar"/>
+ </not>
+ <then>
+ <echo>In then</echo>
+ </then>
+ <elseif>
+ <isset property="antcontrib.jar"/>
+ <then>
+ <echo>In elseif</echo>
+ </then>
+ </elseif>
+ <else>
+ <echo>In else-branch</echo>
+ </else>
+ </if>
+ </target>
+
+ <target name="normalOperationElseif2" depends="setup">
+ <if>
+ <not>
+ <isset property="antcontrib.jar"/>
+ </not>
+ <then>
+ <echo>In then</echo>
+ </then>
+ <elseif>
+ <not>
+ <isset property="antcontrib.jar"/>
+ </not>
+ <then>
+ <echo>In elseif</echo>
+ </then>
+ </elseif>
+ <else>
+ <echo>In else-branch</echo>
+ </else>
+ </if>
+ </target>
+
+</project>
diff --git a/test/resources/logic/limittest.xml b/test/resources/logic/limittest.xml
new file mode 100644
index 0000000..bd3917f
--- /dev/null
+++ b/test/resources/logic/limittest.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0"?>
+
+<project name="limittest" basedir="." default="test1">
+ <description>
+ test build file for the Limit task
+ </description>
+
+ <target name="init">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="test1" depends="init">
+ <!-- should stop 'sleep' task, no failure message -->
+ <limit maxwait="1">
+ <sleep seconds="5"/>
+ <echo>_failed_</echo>
+ <fail/>
+ </limit>
+ </target>
+
+ <property name="ant.enable.asserts" value="true"/>
+ <target name="test2" depends="init">
+ <!-- should not stop 'sleep' task, should print out '_passed_' -->
+ <stopwatch name="limit"/>
+ <limit maxwait="5">
+ <sleep seconds="1"/>
+ <echo>_passed_</echo>
+ </limit>
+ <stopwatch name="limit" action="total"/>
+ <assert message="Too much time.">
+ <bool>
+ <islessthan arg1="${limit}" arg2="2"/>
+ </bool>
+ </assert>
+ </target>
+
+ <target name="test3" depends="init">
+ <!-- test failonerror attribute, build should fail -->
+ <limit maxwait="3" failonerror="true">
+ <fail message="_failed_"/>
+ </limit>
+ </target>
+
+ <target name="test4" depends="init">
+ <!-- test failonerror attribute, build should not fail -->
+ <limit maxwait="3">
+ <fail message="_failed_"/>
+ </limit>
+ </target>
+
+ <target name="test5" depends="init">
+ <limit maxwait="1" unit="minute">
+ <sleep seconds="65"/>
+ </limit>
+ </target>
+
+ <target name="test6" depends="init">
+ <limit seconds="6">
+ <sleep seconds="7"/>
+ </limit>
+ </target>
+
+</project>
diff --git a/test/resources/logic/outofdate.xml b/test/resources/logic/outofdate.xml
new file mode 100644
index 0000000..8442152
--- /dev/null
+++ b/test/resources/logic/outofdate.xml
@@ -0,0 +1,155 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="cleanup">
+ <delete quiet="yes" dir="targets"/>
+ <delete quiet="yes" dir="sources"/>
+ </target>
+
+ <target name="init">
+ <mkdir dir="targets"/>
+ <mkdir dir="sources"/>
+
+ <touch file="sources/s1" millis="100000"/>
+ <touch file="targets/t1" millis="100"/>
+ <touch file="targets/t2" millis="1000000"/>
+ <path id="sources" path="sources/s1"/>
+ <path id="targets">
+ <fileset dir="targets"/>
+ </path>
+ </target>
+
+ <target name="simple" depends="init">
+ <outofdate>
+ <sourcefiles refid="sources"/>
+ <targetfiles refid="targets"/>
+ <sequential>
+ <property name="simple.called" value=""/>
+ </sequential>
+ </outofdate>
+ <fail unless="simple.called">Simple seq not triggered</fail>
+ </target>
+
+ <target name="verbose" depends="init">
+ <outofdate verbose="true">
+ <sourcefiles refid="sources"/>
+ <targetfiles refid="targets"/>
+ </outofdate>
+ </target>
+
+ <target name="delete" depends="init">
+ <outofdate>
+ <sourcefiles refid="sources"/>
+ <targetfiles refid="targets"/>
+ <deletetargets/>
+ </outofdate>
+ <if>
+ <available file="targets/t1"/>
+ <then>
+ <fail>delete failed</fail>
+ </then>
+ </if>
+ <if>
+ <available file="targets/t2"/>
+ <else>
+ <fail>delete too much</fail>
+ </else>
+ </if>
+ </target>
+
+ <target name="delete-all" depends="init">
+ <outofdate>
+ <sourcefiles refid="sources"/>
+ <targetfiles refid="targets"/>
+ <deletetargets all="true"/>
+ </outofdate>
+ <if>
+ <available file="targets/t1"/>
+ <then>
+ <fail>delete failed</fail>
+ </then>
+ </if>
+ <if>
+ <available file="targets/t2"/>
+ <then>
+ <fail>delete all failed</fail>
+ </then>
+ </if>
+ </target>
+
+ <target name="delete-quiet">
+ <outofdate>
+ <sourcefiles refid="sources"/>
+ <targetfiles refid="targets"/>
+ <deletetargets quiet="yes"/>
+ </outofdate>
+ </target>
+
+ <target name="outofdate.init">
+ <!-- generated -->
+ <mkdir dir="outofdate/gen/1/2/3"/>
+ <touch file="outofdate/gen/index.done"/>
+ <touch file="outofdate/gen/1/2/file.done"/>
+ <touch file="outofdate/gen/1/done.c"/>
+ <touch file="outofdate/gen/1/done.h"/>
+ <touch file="outofdate/gen/1/partial.c"/>
+
+ <!-- sources -->
+ <mkdir dir="outofdate/source/1/2/3"/>
+ <touch file="outofdate/source/newer.text"/>
+ <touch file="outofdate/source/1/2/file.notdone"/>
+ <touch file="outofdate/source/1/2/file.done"/>
+ <touch file="outofdate/source/1/done.y"/>
+ <touch file="outofdate/source/1/partial.y"/>
+
+ </target>
+
+ <target name="outofdate.test" depends="outofdate.init">
+ <outofdate
+ outputsources="outofdate.sources"
+ outputtargets="outofdate.targets"
+ alltargets="outofdate.alltargets"
+ outputsourcespath="outofdate.sources.path"
+ outputtargetspath="outofdate.targets.path"
+ >
+ <sourcefiles>
+ <fileset dir="outofdate/source"/>
+ <pathelement path="outofdate.xml"/>
+ </sourcefiles>
+ <targetfiles path="outofdate/gen/index.done"/>
+ <mapper type="glob" from="outofdate/source/1/2/*"
+ to="outofdate/gen/1/2/*"/>
+ <mapper type="glob"
+ from="outofdate/source/*.y"
+ to="outofdate/gen/*.c"/>
+ <mapper type="glob"
+ from="outofdate/source/*.y"
+ to="outofdate/gen/*.h"/>
+ <mapper type="glob"
+ from="outofdate/source/newer.text"
+ to="outofdate.xml"/>
+ <sequential>
+ <echo message="outofdate triggered"/>
+ </sequential>
+ </outofdate>
+ <delete dir="outofdate"/>
+ </target>
+
+ <target name="empty-sources" depends="init">
+ <outofdate>
+ <sourcefiles/>
+ <targetfiles path="THIS IS NOT PRESENT"/>
+ <sequential>
+ <property name="empty-sources.called" value=""/>
+ </sequential>
+ </outofdate>
+ <fail unless="empty-sources.called">Empty sources seq not triggered</fail>
+ </target>
+
+</project>
diff --git a/test/resources/logic/switch.xml b/test/resources/logic/switch.xml
new file mode 100644
index 0000000..fbf8bef
--- /dev/null
+++ b/test/resources/logic/switch.xml
@@ -0,0 +1,87 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="noValue" depends="setup">
+ <switch/>
+ </target>
+
+ <target name="noChildren" depends="setup">
+ <switch value="foo"/>
+ </target>
+
+ <target name="twoDefaults" depends="setup">
+ <switch value="foo">
+ <default/>
+ <default/>
+ </switch>
+ </target>
+
+ <target name="noMatch" depends="setup">
+ <switch value="foo">
+ <case value="bar"/>
+ </switch>
+ </target>
+
+ <target name="caseNoValue" depends="setup">
+ <switch value="foo">
+ <case/>
+ </switch>
+ </target>
+
+ <target name="testDefault" depends="setup">
+ <switch value="foo">
+ <case value="bar">
+ <echo>In case</echo>
+ </case>
+ <default>
+ <echo>In default</echo>
+ <property name="inner" value="baz"/>
+ <echo>${inner}</echo>
+ </default>
+ </switch>
+ </target>
+
+ <target name="testCase" depends="setup">
+ <switch value="foo">
+ <case value="foo">
+ <echo>In case</echo>
+ <property name="inner" value="baz"/>
+ <echo>${inner}</echo>
+ </case>
+ <default>
+ <echo>In default</echo>
+ </default>
+ </switch>
+ </target>
+
+ <target name="testCaseSensitive" depends="setup">
+ <switch value="FOO">
+ <case value="foo">
+ <echo>In case</echo>
+ </case>
+ <default>
+ <echo>In default</echo>
+ </default>
+ </switch>
+ </target>
+
+ <target name="testCaseInSensitive" depends="setup">
+ <switch value="FOO" caseinsensitive="true">
+ <case value="foo">
+ <echo>In case</echo>
+ </case>
+ <default>
+ <echo>In default</echo>
+ </default>
+ </switch>
+ </target>
+
+</project>
diff --git a/test/resources/logic/throw.xml b/test/resources/logic/throw.xml
new file mode 100644
index 0000000..0bea062
--- /dev/null
+++ b/test/resources/logic/throw.xml
@@ -0,0 +1,15 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="useRefid" depends="setup">
+ <throw refid="testref"/>
+ </target>
+</project> \ No newline at end of file
diff --git a/test/resources/logic/timestampselector.xml b/test/resources/logic/timestampselector.xml
new file mode 100644
index 0000000..dd92eb3
--- /dev/null
+++ b/test/resources/logic/timestampselector.xml
@@ -0,0 +1,76 @@
+<project default="init">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <property name="test.dir" value="timestampselector"/>
+ <property name="test.file1" location="${test.dir}/file1.txt" />
+ <property name="test.file2" location="${test.dir}/file2.txt" />
+ <property name="test.dir1" location="${test.dir}/dir1" />
+ <property name="test.dir2" location="${test.dir}/dir2" />
+
+ <fileset id="test.files" dir="${test.dir}">
+ <include name="*.txt" />
+ </fileset>
+
+ <path id="test.files.path">
+ <fileset refid="test.files" />
+ </path>
+
+ <dirset id="test.dirs" dir="${test.dir}">
+ <include name="dir*" />
+ </dirset>
+
+ <path id="test.dirs.path">
+ <dirset refid="test.dirs" />
+ </path>
+
+ <target name="init">
+ <delete quiet ="yes" dir="${test.dir}"/>
+ <mkdir dir="${test.dir}"/>
+ <touch file="${test.dir}/file1.txt" />
+ <touch file="${test.dir}/file2.txt" />
+ <mkdir dir="${test.dir}/dir1"/>
+ <mkdir dir="${test.dir}/dir2"/>
+ </target>
+
+ <target name="teardown">
+ <delete quiet="yes" dir="${test.dir}" />
+ </target>
+
+ <target name="filestamp.fl" depends="init">
+ <timestampselector property="latest.fl.tstamp">
+ <path>
+ <fileset refid="test.files" />
+ </path>
+ </timestampselector>
+
+ <echo message="${latest.fl.tstamp}" />
+ </target>
+
+ <target name="filestamp.pr" depends="init">
+ <timestampselector property="latest.pr.tstamp"
+ pathref="test.files.path" />
+
+ <echo message="${latest.pr.tstamp}" />
+ </target>
+
+ <target name="dirstamp.dl" depends="init">
+ <timestampselector property="latest.dl.tstamp">
+ <path>
+ <dirset refid="test.dirs" />
+ </path>
+ </timestampselector>
+
+ <echo message="${latest.dl.tstamp}" />
+
+ </target>
+
+ <target name="dirstamp.pr" depends="init">
+ <timestampselector property="latest.pr.tstamp"
+ pathref="test.dirs.path" />
+
+ <echo message="${latest.pr.tstamp}" />
+ </target>
+
+</project>
diff --git a/test/resources/logic/trycatch.xml b/test/resources/logic/trycatch.xml
new file mode 100644
index 0000000..b8f020d
--- /dev/null
+++ b/test/resources/logic/trycatch.xml
@@ -0,0 +1,108 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="fullTest" depends="setup">
+ <trycatch property="foo" reference="bar">
+ <try>
+ <fail>Tada!</fail>
+ </try>
+
+ <catch>
+ <echo>In &lt;catch&gt;.</echo>
+ </catch>
+
+ <finally>
+ <echo>In &lt;finally&gt;.</echo>
+ </finally>
+ </trycatch>
+ </target>
+
+ <target name="twoCatches" depends="setup">
+ <trycatch>
+ <try>
+ <fail>Tada!</fail>
+ </try>
+
+ <catch>
+ <echo>In &lt;catch&gt;.</echo>
+ </catch>
+
+ <catch>
+ <echo>In &lt;catch2&gt;.</echo>
+ </catch>
+ </trycatch>
+ </target>
+
+ <target name="twoFinallys" depends="setup">
+ <trycatch>
+ <try>
+ <fail>Tada!</fail>
+ </try>
+
+ <finally>
+ <echo>In &lt;finally&gt;.</echo>
+ </finally>
+
+ <finally>
+ <echo>In &lt;finally2&gt;.</echo>
+ </finally>
+ </trycatch>
+ </target>
+
+ <target name="twoTrys" depends="setup">
+ <trycatch>
+ <try>
+ <fail>Tada!</fail>
+ </try>
+
+ <try>
+ <fail>Tada!</fail>
+ </try>
+
+ <catch>
+ <echo>In &lt;catch&gt;.</echo>
+ </catch>
+
+ <finally>
+ <echo>In &lt;finally&gt;.</echo>
+ </finally>
+ </trycatch>
+ </target>
+
+ <target name="noTry" depends="setup">
+ <trycatch>
+ <catch>
+ <echo>In &lt;catch&gt;.</echo>
+ </catch>
+
+ <finally>
+ <echo>In &lt;finally&gt;.</echo>
+ </finally>
+ </trycatch>
+ </target>
+
+ <target name="noException" depends="setup">
+ <trycatch property="foo" reference="bar">
+ <try>
+ <echo>Tada!</echo>
+ </try>
+
+ <catch>
+ <echo>In &lt;catch&gt;.</echo>
+ </catch>
+
+ <finally>
+ <echo>In &lt;finally&gt;.</echo>
+ </finally>
+ </trycatch>
+ </target>
+
+</project> \ No newline at end of file
diff --git a/test/resources/math/mathtest.xml b/test/resources/math/mathtest.xml
new file mode 100644
index 0000000..df4d731
--- /dev/null
+++ b/test/resources/math/mathtest.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+
+<project name="mathtest" basedir="." default="test1">
+ <description>
+ test build file for the Math task
+ </description>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="test1">
+ <var name="op1" value="12"/>
+ <var name="op2" value="6"/>
+ <var name="op" value="+"/>
+
+ <!-- demo plus -->
+ <math result="result" operand1="${op1}"
+ operation="${op}" operand2="${op2}" datatype="int"/>
+ <echo>${op1} ${op} ${op2} = ${result}</echo>
+ </target>
+</project>
diff --git a/test/resources/platform/osfamily.xml b/test/resources/platform/osfamily.xml
new file mode 100644
index 0000000..c90b07f
--- /dev/null
+++ b/test/resources/platform/osfamily.xml
@@ -0,0 +1,20 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="consistency">
+ <osfamily property="foo"/>
+ <condition property="consistent">
+ <os family="${foo}"/>
+ </condition>
+ </target>
+
+ <target name="missingProperty">
+ <osfamily/>
+ </target>
+</project>
diff --git a/test/resources/platform/shellscript.xml b/test/resources/platform/shellscript.xml
new file mode 100644
index 0000000..fc00d91
--- /dev/null
+++ b/test/resources/platform/shellscript.xml
@@ -0,0 +1,108 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <!-- targets used to check if a shell exists -->
+ <target name="hassh"> <shellscript shell="sh"/> </target>
+ <target name="hasbash"> <shellscript shell="bash"/> </target>
+ <target name="hasperl"> <shellscript shell="perl"/> </target>
+ <target name="haspython"> <shellscript shell="python"/> </target>
+ <target name="hassed">
+ <!-- Temporary hack, since SED is hanging the tests on windows -->
+ <fail />
+ <shellscript shell="sed"/>
+ </target>
+ <target name="hascmd">
+ <shellscript shell="cmd.exe" tmpsuffix=".bat">
+ <arg value="/C" />
+ echo a
+ </shellscript>
+ </target>
+
+ <target name="sh.hello">
+ <shellscript shell="sh">
+ echo "hello world"
+ </shellscript>
+ </target>
+
+ <target name="bash.hello">
+ <shellscript shell="bash">
+ echo "hello world"
+ </shellscript>
+ </target>
+
+ <!-- python needs to start on the first col -->
+ <target name="python.hello">
+ <shellscript shell="python">
+print "hello world"
+ </shellscript>
+ </target>
+
+ <target name="perl.hello">
+ <shellscript shell="perl">
+ print STDOUT "hello world\n";
+ </shellscript>
+ </target>
+
+ <target name="noshell">
+ <shellscript shell="!!!!^^^a shell that should not exist^^^^^!!!!"/>
+ </target>
+
+
+ <target name="sh.inputstring">
+ <shellscript shell="sh" inputstring="echo hello world"/>
+ </target>
+
+ <target name="sed.test">
+ <shellscript shell="sed" >
+ <arg value="-e"/>
+ <arg value="s/FOO/BAR/g"/>
+ FOO bar bar bar FOO bar bar
+ </shellscript>
+ </target>
+
+ <target name="sh.property">
+ <property name="my.sh.property" value="this is a property"/>
+ <shellscript executable="sh">
+ echo ${my.sh.property}
+ </shellscript>
+ </target>
+
+ <target name="sh.set.property">
+ <shellscript shell="sh" outputproperty="sh.set.property">
+ echo hello world
+ </shellscript>
+ </target>
+
+ <target name="sh.tmp.suffix">
+ <shellscript shell="sh" tmpsuffix=".bat">
+ echo $0
+ </shellscript>
+ </target>
+
+ <target name="cmd.test">
+ <shellscript shell="cmd.exe" tmpsuffix=".bat">
+ <arg value="/C"/>
+ <arg value="call"/>
+ echo hello world
+ </shellscript>
+ </target>
+
+ <target name="dir.test">
+ <mkdir dir="subdir"/>
+ <shellscript shell="sh" dir="subdir" outputproperty="dir.test.property">
+ current=`pwd`
+ echo "dir is $current"
+ </shellscript>
+ <delete dir="subdir"/>
+ </target>
+
+ <target name="command.test">
+ <shellscript command="this should not work"/>
+ </target>
+</project>
diff --git a/test/resources/property/pathtofileset.xml b/test/resources/property/pathtofileset.xml
new file mode 100644
index 0000000..b330cdf
--- /dev/null
+++ b/test/resources/property/pathtofileset.xml
@@ -0,0 +1,45 @@
+<project default="simple">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="cleanup">
+ <delete quiet ="yes" dir="${test.dir}"/>
+ </target>
+
+ <target name="init">
+ <property name="test.dir" value="pathtofilesset"/>
+ <mkdir dir="${test.dir}/0/0"/>
+ <mkdir dir="${test.dir}/0/1"/>
+ <mkdir dir="${test.dir}/1/0"/>
+ <mkdir dir="${test.dir}/1/1"/>
+ <touch file="${test.dir}/0/0/0.java"/>
+ <touch file="${test.dir}/0/1/1.java"/>
+ <touch file="${test.dir}/1/0/2.java"/>
+ <touch file="${test.dir}/1/1/3.java"/>
+ </target>
+
+ <target name="simple" depends="init">
+ <path id="simple">
+ <fileset dir="${test.dir}/0" includes="**/*.java"/>
+ <fileset dir="${test.dir}/1" includes="**/*.java"/>
+ </path>
+ <pathtofileset dir="${test.dir}/0" pathrefid="simple"
+ ignoreNonRelative="yes" name="simple.0.fileset"/>
+ <pathconvert targetos="unix" refid="simple.0.fileset" property="simple.0.property"/>
+
+ <pathtofileset dir="${test.dir}/1" pathrefid="simple"
+ ignoreNonRelative="yes" name="simple.1.fileset"/>
+ <pathconvert targetos="unix" refid="simple.1.fileset" property="simple.1.property"/>
+ </target>
+
+ <target name="simple-exception" depends="init">
+ <path id="simple">
+ <fileset dir="${test.dir}/0" includes="**/*.java"/>
+ <fileset dir="${test.dir}/1" includes="**/*.java"/>
+ </path>
+ <pathtofileset dir="${test.dir}/0" pathrefid="simple"
+ name="simple.0.fileset"/>
+ </target>
+
+</project>
diff --git a/test/resources/property/propertycopy.xml b/test/resources/property/propertycopy.xml
new file mode 100644
index 0000000..9425416
--- /dev/null
+++ b/test/resources/property/propertycopy.xml
@@ -0,0 +1,33 @@
+<project default="invalid">
+ <target name="invalid">
+ <fail>Don't call this file directly.</fail>
+ </target>
+
+ <target name="setup">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ </target>
+
+ <target name="missingName" depends="setup">
+ <propertycopy from="foo"/>
+ </target>
+
+ <target name="missingFrom" depends="setup">
+ <propertycopy name="foo"/>
+ </target>
+
+ <target name="nonSilent" depends="setup">
+ <propertycopy name="foo" from="bar"/>
+ </target>
+
+ <target name="silent" depends="setup">
+ <propertycopy name="foo" from="bar" silent="true"/>
+ </target>
+
+ <target name="normal" depends="setup">
+ <property name="org" value="MyOrg" />
+ <property name="org.MyOrg.DisplayName" value="My Organiziation" />
+ <propertycopy name="displayName" from="org.${org}.DisplayName" />
+ </target>
+</project> \ No newline at end of file
diff --git a/test/resources/property/propertyselector.properties b/test/resources/property/propertyselector.properties
new file mode 100644
index 0000000..8df9c0e
--- /dev/null
+++ b/test/resources/property/propertyselector.properties
@@ -0,0 +1,7 @@
+#Module 1 Properties
+module.Module1.id=1
+module.Module1.name=Module 1
+
+#Module 2 Properties
+module.Module2.id=2
+module.Module2.name=Module 2
diff --git a/test/resources/property/propertyselector.xml b/test/resources/property/propertyselector.xml
new file mode 100644
index 0000000..d03eea0
--- /dev/null
+++ b/test/resources/property/propertyselector.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="Project" default="build" basedir=".">
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties" />
+
+ <property file="propertyselector.properties" />
+
+ <target name="init">
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+ <property file="propertyselector.properties" />
+ </target>
+
+ <target name="select.test.grouping.0" depends="init">
+ <propertyselector property="module.list"
+ match="module\.([^\.]*)\.id"
+ delimiter=","
+ casesensitive="false" />
+
+ <echo message="${module.list}" />
+ </target>
+
+ <target name="select.test.grouping.1" depends="init">
+ <propertyselector property="module.list"
+ match="module\.([^\.]*)\.id"
+ select="\1"
+ delimiter=","
+ casesensitive="false" />
+
+ <echo message="${module.list}" />
+ </target>
+
+</project>
diff --git a/test/resources/property/variabletest.xml b/test/resources/property/variabletest.xml
new file mode 100644
index 0000000..534743e
--- /dev/null
+++ b/test/resources/property/variabletest.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0"?>
+
+<project name="variabletest" basedir="." default="test1">
+ <description>
+ test build file for the Variable task
+ </description>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <!-- use like a standard property -->
+ <target name="test1">
+ <var name="x" value="6" />
+ </target>
+
+ <!-- use like a standard property -->
+ <target name="test2">
+ <var name="x" value="12" />
+ </target>
+
+ <!-- can append to itself -->
+ <target name="test3">
+ <var name="x" value="12" />
+ <var name="x" value="6 + ${x}" /> <!-- 6 + 12 -->
+ </target>
+
+ <!-- property can't override -->
+ <target name="test4">
+ <var name="x" value="6" />
+ <property name="x" value="12" />
+ </target>
+
+ <!-- can append multiple times -->
+ <target name="test5">
+ <var name="str" value="I" />
+ <var name="str" value="${str} am" />
+ <var name="str" value="${str} a" />
+ <var name="str" value="${str} string." />
+ <!-- I am a string. -->
+ </target>
+
+ <!-- property can't override -->
+ <target name="test6">
+ <var name="x" value="blue" />
+ <tstamp>
+ <format property="x" pattern="EEEE" />
+ </tstamp>
+ <var name="x" value="Today is ${x}."/>
+ <!-- Today is blue. -->
+ </target>
+
+ <!-- can override property -->
+ <target name="test7">
+ <property name="x" value="12" />
+ <var name="x" value="6" />
+ </target>
+
+ <!-- TODO: uses the Antelope <if>, need to adjust to use ant-contrib <if>
+ <target name="test8">
+ <var name="x" value="6"/>
+ <if name="x" value="6">
+ <var name="x" value="12"/>
+ <else>
+ <var name="x" value="13"/>
+ </else>
+ </if>
+ <echo>${x}</echo>
+ </target>
+ -->
+
+ <target name="test9">
+ <property name="i" value="2"/>
+ <var name="i" unset="true"/>
+ </target>
+
+ <target name="test10">
+ <var name="x" value="test"/>
+ <var name="x" unset="true"/>
+ <property name="x" value="xxx"/>
+ </target>
+</project>
diff --git a/test/resources/walls/compilewithwalls.xml b/test/resources/walls/compilewithwalls.xml
new file mode 100644
index 0000000..6298d76
--- /dev/null
+++ b/test/resources/walls/compilewithwalls.xml
@@ -0,0 +1,237 @@
+<project name="test_compilewithwalls" basedir="." default="cleanup">
+ <property name="test.dir" value="compilewithwalls"/>
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath location="${antcontrib.jar}"/>
+ </taskdef>
+
+ <target name="cleanup">
+ <delete quiet="yes" dir="${test.dir}"/>
+ </target>
+
+ <target name="init">
+ </target>
+
+ <target name="testTooManyNestedWallElements" depends="init">
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls />
+ <walls />
+ <javac />
+ </compilewithwalls>
+ </target>
+
+ <target name="testTooManyNestedJavacElements" depends="init">
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls />
+ <javac />
+ <javac />
+ </compilewithwalls>
+ </target>
+
+ <target name="testNoWallElement" depends="init">
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <javac />
+ </compilewithwalls>
+ </target>
+
+ <target name="testNoJavacElement" depends="init">
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls />
+ </compilewithwalls>
+ </target>
+
+ <target name="testNoSrcDirInJavac" depends="init">
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls>
+ <package name="modA" package="biz.xsoftware" />
+ </walls>
+
+ <javac>
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testIntermediaryDirAndDestDirSame" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir1">
+ <walls>
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testIntermediaryDirInsideDestDir" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir1/insideDestDir">
+ <walls>
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testPackageDoesntEndWithStar" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls>
+ <package name="modA" package="biz.xsoftware" />
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+ <target name="testPackageDoesntHaveSlash" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls>
+ <package name="modA" package="biz/xsoftware.*" />
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testDependsOnNonExistPackage" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls>
+ <package name="modA"
+ package="biz.xsoftware.*"
+ depends="modB" />
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+ <target name="testDependsOnPackageAfter" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+
+ <compilewithwalls intermediaryBuildDir="${test.dir}/dir2">
+ <walls>
+ <package name="modA"
+ package="biz.xsoftware.*"
+ depends="modB" />
+ <package name="modB"
+ package="biz.xsoftware.something.*" />
+ </walls>
+
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+ <target name="testPackageABreakingWhenAIsCompiledFirst" depends="init">
+ <mkdir dir="${test.dir}/classes/testA" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/classes/testAtemp">
+ <walls>
+ <package name="modA"
+ package="mod.modA.*" />
+ <package name="modB"
+ package="mod.modB.*" />
+ <package name="mod"
+ package="mod.*"
+ depends="modA,modB" />
+ </walls>
+
+ <javac srcdir="./testA" destdir="${test.dir}/classes/testA">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+ <target name="testPackageBBreakingWhenAIsCompiledFirst" depends="init">
+ <mkdir dir="${test.dir}/classes/testB" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/classes/testBtemp">
+ <walls>
+ <package name="modA"
+ package="mod.modA.*" />
+ <package name="modB"
+ package="mod.modB.*" />
+ <package name="mod"
+ package="mod.*"
+ depends="modA,modB" />
+ </walls>
+
+ <javac srcdir="./testB" destdir="${test.dir}/classes/testB">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+ <target name="testMoreThanOneSrcDirInJavac" depends="init">
+ <mkdir dir="${test.dir}/classes/testX" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/classes/testXtemp">
+ <walls/>
+ <javac destdir="${test.dir}/classes/testX">
+ <src path="${test.dir}/dir1">
+ </src>
+ <src path="xyz">
+ </src>
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testCompileOfAllUsingDepends" depends="init">
+ <mkdir dir="${test.dir}/classes/testC" />
+ <compilewithwalls intermediaryBuildDir="${test.dir}/classes/testCtemp">
+ <walls>
+ <package name="modA"
+ package="mod.modA.*" />
+ <package name="modB"
+ package="mod.modB.*" />
+ <package name="mod"
+ package="mod.*"
+ depends="modA,modB" />
+ </walls>
+
+ <javac srcdir="./testC" destdir="${test.dir}/classes/testC">
+ </javac>
+ </compilewithwalls>
+
+ </target>
+
+<!--
+*********************************************************
+ These are mostly the same tests above but making sure it works with
+ external walls.xml file.
+*********************************************************
+-->
+ <target name="testDependsOnPackageAfterExternalWalls" depends="init">
+ <mkdir dir="${test.dir}/dir1" />
+ <compilewithwalls walls="dependsafter.xml" intermediaryBuildDir="${test.dir}/dir2">
+ <javac srcdir="${test.dir}/dir1" destdir="${test.dir}/dir1">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testPackageBBreakingWhenAIsCompiledFirstExternalWalls" depends="init">
+ <mkdir dir="${test.dir}/classes/testB" />
+ <compilewithwalls walls="packageB-break.xml" intermediaryBuildDir="${test.dir}/classes/testBtemp">
+ <javac srcdir="./testB" destdir="${test.dir}/classes/testB">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+ <target name="testCompileOfAllUsingDependsExternalWalls" depends="init">
+ <mkdir dir="${test.dir}/classes/testC" />
+ <compilewithwalls walls="walls.xml" intermediaryBuildDir="${test.dir}/classes/testCtemp">
+ <javac srcdir="./testC" destdir="${test.dir}/classes/testC">
+ </javac>
+ </compilewithwalls>
+ </target>
+
+</project>
diff --git a/test/resources/walls/dependsafter.xml b/test/resources/walls/dependsafter.xml
new file mode 100644
index 0000000..30aac80
--- /dev/null
+++ b/test/resources/walls/dependsafter.xml
@@ -0,0 +1,7 @@
+ <walls>
+ <package name="modA"
+ package="biz.xsoftware.*"
+ depends="modB" />
+ <package name="modB"
+ package="biz.xsoftware.something.*" />
+ </walls> \ No newline at end of file
diff --git a/test/resources/walls/packageB-break.xml b/test/resources/walls/packageB-break.xml
new file mode 100644
index 0000000..4fa8bb3
--- /dev/null
+++ b/test/resources/walls/packageB-break.xml
@@ -0,0 +1,9 @@
+<walls>
+ <package name="modA"
+ package="mod.modA.*" />
+ <package name="modB"
+ package="mod.modB.*" />
+ <package name="mod"
+ package="mod.*"
+ depends="modA,modB" />
+</walls> \ No newline at end of file
diff --git a/test/resources/walls/testA/mod/modA/ModuleA.java b/test/resources/walls/testA/mod/modA/ModuleA.java
new file mode 100644
index 0000000..6950bdc
--- /dev/null
+++ b/test/resources/walls/testA/mod/modA/ModuleA.java
@@ -0,0 +1,10 @@
+
+package mod.modA;
+
+import mod.modB.ModuleB;
+
+public class ModuleA
+{
+ private ModuleB moduleB;
+
+}; \ No newline at end of file
diff --git a/test/resources/walls/testA/mod/modB/ModuleB.java b/test/resources/walls/testA/mod/modB/ModuleB.java
new file mode 100644
index 0000000..10175b5
--- /dev/null
+++ b/test/resources/walls/testA/mod/modB/ModuleB.java
@@ -0,0 +1,6 @@
+
+package mod.modB;
+
+public class ModuleB
+{
+}; \ No newline at end of file
diff --git a/test/resources/walls/testB/mod/modA/TestBModuleA.java b/test/resources/walls/testB/mod/modA/TestBModuleA.java
new file mode 100644
index 0000000..b6b7929
--- /dev/null
+++ b/test/resources/walls/testB/mod/modA/TestBModuleA.java
@@ -0,0 +1,7 @@
+
+package mod.modA;
+
+public class TestBModuleA
+{
+
+}; \ No newline at end of file
diff --git a/test/resources/walls/testB/mod/modB/TestBModuleB.java b/test/resources/walls/testB/mod/modB/TestBModuleB.java
new file mode 100644
index 0000000..c7428ff
--- /dev/null
+++ b/test/resources/walls/testB/mod/modB/TestBModuleB.java
@@ -0,0 +1,9 @@
+
+package mod.modB;
+
+import mod.modA.TestBModuleA;
+
+public class TestBModuleB
+{
+ private TestBModuleA temp;
+}; \ No newline at end of file
diff --git a/test/resources/walls/testC/mod/TestCModule.java b/test/resources/walls/testC/mod/TestCModule.java
new file mode 100644
index 0000000..5d9c0e8
--- /dev/null
+++ b/test/resources/walls/testC/mod/TestCModule.java
@@ -0,0 +1,11 @@
+
+package mod;
+
+import mod.modA.TestCModuleA;
+import mod.modB.TestCModuleB;
+
+public class TestCModule
+{
+ private TestCModuleA temp1;
+ private TestCModuleB temp2;
+}; \ No newline at end of file
diff --git a/test/resources/walls/testC/mod/modA/TestCModuleA.java b/test/resources/walls/testC/mod/modA/TestCModuleA.java
new file mode 100644
index 0000000..8b9f8d6
--- /dev/null
+++ b/test/resources/walls/testC/mod/modA/TestCModuleA.java
@@ -0,0 +1,7 @@
+
+package mod.modA;
+
+public class TestCModuleA
+{
+
+}; \ No newline at end of file
diff --git a/test/resources/walls/testC/mod/modB/TestCModuleB.java b/test/resources/walls/testC/mod/modB/TestCModuleB.java
new file mode 100644
index 0000000..989ebdf
--- /dev/null
+++ b/test/resources/walls/testC/mod/modB/TestCModuleB.java
@@ -0,0 +1,7 @@
+
+package mod.modB;
+
+
+public class TestCModuleB
+{
+}; \ No newline at end of file
diff --git a/test/resources/walls/walls.xml b/test/resources/walls/walls.xml
new file mode 100644
index 0000000..d5ca6b8
--- /dev/null
+++ b/test/resources/walls/walls.xml
@@ -0,0 +1,9 @@
+<walls>
+ <package name="modA"
+ package="mod.modA.*" />
+ <package name="modB"
+ package="mod.modB.*" />
+ <package name="mod"
+ package="mod.*"
+ depends="modA,modB" />
+</walls> \ No newline at end of file
diff --git a/test/src/net/sf/antcontrib/BuildFileTestBase.java b/test/src/net/sf/antcontrib/BuildFileTestBase.java
new file mode 100644
index 0000000..9764d23
--- /dev/null
+++ b/test/src/net/sf/antcontrib/BuildFileTestBase.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.URL;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileTest;
+
+
+/**
+ * More methods for BuildFileTest.
+ *
+ * @author Dale Anson
+ */
+public abstract class BuildFileTestBase extends BuildFileTest {
+
+ /**
+ * Constructor for the BuildFileTestBase object
+ *
+ * @param name string to pass up to TestCase constructor
+ */
+ public BuildFileTestBase( String name ) {
+ super( name );
+ }
+
+ /**
+ * run a target, expect a build exception
+ *
+ * @param target target to run
+ */
+ protected void expectBuildException( String target ) {
+ expectSpecificBuildException( target, "no specific reason", null );
+ }
+
+ /**
+ * Assert that the given message has NOT been logged with a priority &gt;= INFO
+ * when running the given target.
+ *
+ * @param target Description of the Parameter
+ * @param log Description of the Parameter
+ */
+ protected void expectLogNotContaining( String target, String log ) {
+ executeTarget( target );
+ String realLog = getLog();
+ assertTrue( "expecting log to NOT contain \"" + log + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf( log ) < 0 );
+ }
+
+ /**
+ * set up to run the named project
+ * <p>
+ * Overrides BuildFileTest.configureProject to first
+ * attempt to make a File out of the filename parameter, if the resulting
+ * file does not exists, then attempt to locate the file in the classpath.
+ * This way, test xml files can be placed alongside of their corresponding
+ * class file and can be easily found.
+ *
+ * @param filename name of project file to run
+ * @exception BuildException Description of the Exception
+ */
+ protected void configureProject( String filename ) throws BuildException {
+ // find the build file
+ File f = new File( filename );
+ if ( !f.exists() ) {
+ URL url = getClass().getClassLoader().getResource( filename );
+ if ( url == null )
+ throw new BuildException( "Can't find " + filename );
+ f = new File( url.getPath() );
+ if ( !f.exists() )
+ throw new BuildException( "Can't find " + filename );
+ }
+ super.configureProject(f.getAbsolutePath());
+ }
+
+ /**
+ * run a target, expect an exception string containing the substring we look
+ * for (case sensitive match)
+ *
+ * @param target target to run
+ * @param cause information string to reader of report
+ * @param contains substring of the build exception to look for
+ */
+ protected void expectBuildExceptionStackTraceContaining( String target, String cause, String contains ) {
+ try {
+ executeTarget( target );
+ }
+ catch ( org.apache.tools.ant.BuildException ex ) {
+ //buildException = ex; // buildException has private access in super
+ StringWriter stacktrace = new StringWriter();
+ PrintWriter writer = new PrintWriter( stacktrace, true );
+ ex.printStackTrace( writer );
+ String trace = stacktrace.toString();
+ if ( ( null != contains ) && ( trace.indexOf( contains ) == -1 ) ) {
+ fail( "Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + trace + "' instead)" );
+ }
+ return;
+ }
+ fail( "Should throw BuildException because: " + cause );
+ }
+}
+
diff --git a/test/src/net/sf/antcontrib/antclipse/AntclipseTest.java b/test/src/net/sf/antcontrib/antclipse/AntclipseTest.java
new file mode 100644
index 0000000..973a8b9
--- /dev/null
+++ b/test/src/net/sf/antcontrib/antclipse/AntclipseTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antclipse;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Basic test for "antclipse" task. For the moment it just launches the test xml script.
+ * @author Adrian Spinei [email protected]
+ * @version $Revision: 1.2 $
+ */
+public class AntclipseTest extends BuildFileTest
+{
+
+ /**
+ * Simple overriden constructor
+ * @param arg0
+ */
+ public AntclipseTest(String arg0)
+ {
+ super(arg0);
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#setUp()
+ */
+ public void setUp()
+ {
+ configureProject("test/resources/antclipse/antclipsetest.xml");
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#tearDown()
+ */
+ public void tearDown()
+ {
+ //nothing to do
+ }
+
+ /**
+ * Launches the "everything" task. Should not throw errors.
+ */
+ public void testExecuteDefaultBuild()
+ {
+ executeTarget("everything");
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/antserver/AntServerTest.java b/test/src/net/sf/antcontrib/antserver/AntServerTest.java
new file mode 100644
index 0000000..24cdca9
--- /dev/null
+++ b/test/src/net/sf/antcontrib/antserver/AntServerTest.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.antserver;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+
+/****************************************************************************
+ * Place class description here.
+ *
+ * @author inger
+ * @author <additional author>
+ *
+ * @since
+ *
+ ****************************************************************************/
+
+
+public class AntServerTest
+ extends BuildFileTestBase
+{
+ public AntServerTest(String name)
+ {
+ super(name);
+ }
+
+
+ public void setUp()
+ {
+ configureProject("test/resources/antserver/antservertest.xml");
+ }
+
+ public void tearDown()
+ {
+ executeTarget("cleanup");
+ }
+
+ public void test1()
+ {
+ String expected[] = new String[]
+ {
+ "Test1 Successfully Called",
+ "[test1_remote]"
+ };
+
+ expectLogContaining("test1", expected);
+ }
+
+ public void test2()
+ {
+ String expected[] = new String[]
+ {
+ "Test2 Successfully Called",
+ "[test2_remote]"
+ };
+
+ expectLogContaining("test2", expected);
+ }
+
+ public void test3()
+ {
+ String expected[] = new String[]
+ {
+ "Test3 Successfully Called",
+ "[test3_remote]"
+ };
+
+ expectLogContaining("test3", expected);
+ }
+
+ public void test4()
+ {
+ String expected[] = new String[]
+ {
+ "Test4 Successfully Called",
+ "[test4_remote]"
+ };
+
+ expectLogContaining("test4", expected);
+ }
+
+ public void test5()
+ {
+ this.executeTarget("test5");
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority
+ * &gt;= INFO when running the given target.
+ */
+ protected void expectLogContaining(String target,
+ String logs[])
+ {
+ executeTarget(target);
+ String realLog = getLog();
+
+ int cnt = 0;
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < logs.length; i++)
+ {
+ if (realLog.indexOf(logs[i]) >= 0)
+ cnt++;
+ if (i != 0)
+ sb.append(" and ");
+ sb.append("\"").append(logs[i]).append("\"");
+ }
+
+
+ assertTrue("expecting log to contain " + sb.toString()
+ + " log was \"" + realLog + "\"",
+ cnt == logs.length);
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/design/VerifyDesignTest.java b/test/src/net/sf/antcontrib/design/VerifyDesignTest.java
new file mode 100644
index 0000000..746448c
--- /dev/null
+++ b/test/src/net/sf/antcontrib/design/VerifyDesignTest.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2001-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.design;
+
+import java.io.File;
+
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+import org.apache.tools.ant.BuildFileTest;
+import org.apache.tools.ant.util.JavaEnvUtils;
+
+/**
+ * BIG NOTE***************************************************
+ * Always expect specific exceptions. Most of these test cases when
+ * first submitted were not and therefore were not testing what they said
+ * they were testing. Exceptions were being caused by other things and the
+ * tests were still passing. Now all tests expect a specific exception
+ * so if any other is thrown we will fail the test case.
+ * ************************************************************
+ *
+ * Testcase for <propertycopy>.
+ */
+public class VerifyDesignTest extends BuildFileTest {
+
+ private final static String REASON = "Build should have failed with proper message and did not";
+ private String baseDir = "test"+File.separator
+ +"resources"+File.separator
+ +"design"+File.separator;
+ private String c = File.separator;
+
+ public VerifyDesignTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+
+ configureProject("test/resources/design/verifydesign.xml");
+// project.log("ASFDSADF", Project.MSG_INFO);
+ }
+
+ private static String s = "";
+
+ public static void log(String msg) {
+ s += msg+"\n";
+ }
+
+ public void tearDown() {
+ executeTarget("cleanup");
+
+ //System.out.println("test log=\n"+s);
+ }
+
+ public void testArrayDepend() {
+ String class1 = "mod.arraydepend.ClassDependsOnArray";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testArrayDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testArrayDepend2() {
+ executeTarget("testArrayDepend2");
+ }
+
+ public void testArrayDepend3() {
+ String class1 = "mod.arraydepend3.ClassDependsOnArray";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testArrayDepend3", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testBadXML() {
+ File designFile = new File("test/resources/design/designfiles/badxml.xml");
+ String msg = "\nProblem parsing design file='"
+ + designFile.getAbsolutePath() + "'. \nline=3 column=1 Reason:\nElement type \"design\" must be followed by either attribute specifications, \">\" or \"/>\".\n";
+ expectSpecificBuildException("testBadXML", REASON, msg);
+ }
+
+ public void testCastDepend() {
+ String class1 = "mod.castdepend.ClassDependsOnCast";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testCastDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testCatchDepend() {
+ String class1 = "mod.catchdepend.ClassDependsOnCatch";
+ String class2 = "mod.dummy.DummyRuntimeException";
+ expectDesignCheckFailure("testCatchDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testClassFiles() {
+ String class1 = "mod.castdepend.ClassDependsOnCast";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testClassFiles", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testDeclareJavaUtil() {
+ executeTarget("testDeclareJavaUtil");
+ }
+
+ public void testDeclareJavaUtilFail() {
+ String class1 = "mod.declarejavautil.ClassDependsOnJavaUtil";
+ String class2 = "java.util.List";
+ expectDesignCheckFailure("testDeclareJavaUtilFail", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testDeclareJavax() {
+ String class1 = "mod.declarejavax.ClassDependsOnJavax";
+ String class2 = "javax.swing.JButton";
+ expectDesignCheckFailure("testDeclareJavax", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testDeclareJavaxPass() {
+ executeTarget("testDeclareJavaxPass");
+ }
+
+
+ //tests to write
+
+ //depend on java.util should pass by default
+ //depend on java.util should fail after defining needDeclareTrue
+ //depend on javax.swing should pass after needDeclareFalse
+
+ //depend on dummy should pass after needDeclareFalse
+
+ public void testFieldDepend() {
+ String class1 = "mod.fielddepend.ClassDependsOnField";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testFieldDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testFieldRefDepend() {
+ if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)
+ || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
+ || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3)) {
+ return;
+ }
+
+ String class1 = "mod.fieldrefdepend.ClassDependsOnReferenceInFieldDeclaration";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testFieldRefDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testInnerClassDepend() {
+ String class1 = "mod.innerclassdepend.InnerClassDependsOnSuper$Inner";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testInnerClassDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testInstanceOfDepend() {
+ String class1 = "mod.instanceofdepend.ClassDependsOnInstanceOf";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testInstanceOfDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testInterfaceDepend() {
+ String class1 = "mod.interfacedepend.ClassDependsOnInterfaceMod2";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testInterfaceDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testLocalVarDepend() {
+ String class1 = "mod.localvardepend.ClassDependsOnLocalVar";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testLocalVarDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testLocalVarRefDepend() {
+ if (JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_1)
+ || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_2)
+ || JavaEnvUtils.isJavaVersion(JavaEnvUtils.JAVA_1_3)) {
+ return;
+ }
+ String class1 = "mod.localvarrefdepend.ClassDependsOnLocalVariableReference";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testLocalVarRefDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testMissingAttribute() {
+ File designFile = new File("test/resources/design/designfiles/missingattribute.xml");
+ String msg = "\nProblem parsing design file='"
+ + designFile.getAbsolutePath() + "'. \nline=3 column=31 Reason:\nError in file="
+ + designFile.getAbsolutePath() + ", package element must contain the 'name' attribute\n";
+ expectSpecificBuildException("testMissingAttribute", REASON, msg);
+ }
+
+ public void testMultipleErrors() {
+ File jarFile = new File(baseDir+File.separator+"build"+File.separator+"jar"
+ +File.separator+"test.jar");
+ String class1 = "mod.arraydepend.ClassDependsOnArray";
+ String class2 = "mod.dummy.DummyClass";
+ //executeTarget("testMultipleErrors");
+ String error1 = Design.getWrapperMsg(jarFile, Design.getErrorMessage(class1, class2));
+ class1 = "mod.castdepend.ClassDependsOnCast";
+ String error2 = Design.getWrapperMsg(jarFile, Design.getNoDefinitionError(class1));
+ class1 = "mod.catchdepend.ClassDependsOnCatch";
+ class2 = "mod.dummy.DummyRuntimeException";
+ String error3 = Design.getWrapperMsg(jarFile, Design.getErrorMessage(class1, class2));
+ String s = "\nEvaluating package=mod.arraydepend"+error1;
+ s += "\nEvaluating package=mod.castdepend"+error2;
+ s += "\nEvaluating package=mod.catchdepend"+error3;
+ s += "\nEvaluating package=mod.dummy";
+
+// executeTarget("testMultipleErrors");
+ expectDesignCheckFailure("testMultipleErrors", s);
+ }
+
+ public void testNewDepend() {
+ String class1 = "mod.newdepend.ClassDependsOnNew";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testNewDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testNewDepend2() {
+ String class1 = "mod.newdepend2.ClassDependsOnNewInField";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testNewDepend2", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testNoDebugOption() {
+ String class1 = "mod.nodebugoption.ClassDependsOnLocalVar";
+ expectDesignCheckFailure("testNoDebugOption", VisitorImpl.getNoDebugMsg(class1));
+ }
+ public void testNoJar() {
+ File jar = new File("test/resources/design/build/jar/test.jar");
+ expectSpecificBuildException("testNoJar", REASON, VisitorImpl.getNoFileMsg(jar));
+ }
+
+ public void testParamDepend() {
+ String class1 = "mod.paramdepend.ClassDependsOnParameter";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testParamDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testPassLocalDepend() {
+ executeTarget("testPassLocalDepend");
+ }
+
+ public void testPathElementLocation() {
+ executeTarget("testPathElementLocation");
+ }
+
+ public void testPathElementPath() {
+ executeTarget("testPathElementPath");
+ }
+
+ public void testPutStatic() {
+ executeTarget("testPutStatic");
+ }
+
+ public void testRecursion() {
+ executeTarget("testRecursion");
+ }
+
+ public void testRecursion2() {
+ executeTarget("testRecursion2");
+ }
+
+ public void testRecursion3() {
+ executeTarget("testRecursion3");
+ }
+
+ public void testReturnValDepend() {
+ String class1 = "mod.returnvaldepend.ClassDependsOnReturnValue";
+ String class2 = "mod.dummy.DummyInterface";
+ expectDesignCheckFailure("testReturnValDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testSignatureExceptionDepend() {
+ String class1 = "mod.signatureexceptiondepend.ClassDependsOnExceptionInMethodSignature";
+ String class2 = "mod.dummy.DummyException";
+ expectDesignCheckFailure("testSignatureExceptionDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testStaticDepend() {
+ String class1 = "mod.staticdepend.ClassDependsOnStatic";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testStaticDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testStaticField2Depend() {
+ String class1 = "mod.staticfield2depend.ClassDependsOnStaticField";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testStaticField2Depend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testStaticFieldDepend() {
+ String class1 = "mod.staticfielddepend.ClassDependsOnStaticField";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testStaticFieldDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testStaticFinalDepend() {
+ //This is an impossible test since javac compiles String and primitive constants into the code
+ //losing any reference to the class that contains the constant...In this one instance,
+ //verifydesign can't verify that constant imports don't violate the design!!!!
+ //check out mod.staticfinaldepend.ClassDependsOnStaticField to see the code
+ //that will pass the design even if it is violating it.
+ // String class1 = "mod.staticfinaldepend.ClassDependsOnConstant";
+ // String class2 = "mod.dummy.DummyClass";
+ // expectDesignCheckFailure("testStaticFinalDepend", Design.getErrorMessage(class1, class2));
+ }
+
+ public void testSuperDepend() {
+ String s = File.separator;
+ File f = new File("test"+s+"resources"+s+"design"+s+"build"+s+"jar"+s+"test.jar");
+
+ // executeTarget("testSuperDepend");
+ String class1 = "mod.superdepend.ClassDependsOnSuperMod2";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testSuperDepend", Design.getErrorMessage(class1, class2));
+
+ //jar file should have been deleted
+ assertTrue("jar file should not exist yet still does", !f.exists());
+ }
+
+ public void testWarSuccess() {
+ executeTarget("testWarSuccess");
+ }
+
+ public void testWarFailure() {
+ String class1 = "mod.warfailure.ClassDependsOnSuperMod2";
+ String class2 = "mod.dummy.DummyClass";
+ expectDesignCheckFailure("testWarFailure", Design.getErrorMessage(class1, class2));
+ }
+
+ public static void main(String[] args) {
+ TestSuite suite = new TestSuite();
+ suite.addTest(new VerifyDesignTest("testArrayDepend2"));
+ TestRunner.run(suite);
+ }
+
+ private void expectDesignCheckFailure(String target, String message) {
+ expectSpecificBuildException(target, "Design is broken",
+ "Design check failed due to previous "
+ + "errors");
+ assertLogContaining(message);
+ }
+}
diff --git a/test/src/net/sf/antcontrib/logic/AntCallBackTest.java b/test/src/net/sf/antcontrib/logic/AntCallBackTest.java
new file mode 100644
index 0000000..3635002
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/AntCallBackTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+/**
+ * Since AntCallBack is basically a copy and paste of antcall, the only testing
+ * done here is on the extra features provided by antcallback. It is assumed
+ * that changes to antcall will be propagated to antcallback and that antcall
+ * has it's own unit tests (which turns out to have been a bad assumption,
+ * I can't find any unit tests for antcall).
+ *
+ * @author danson
+ */
+public class AntCallBackTest extends BuildFileTestBase {
+
+ /**
+ * Constructor for the AntCallBackTest object
+ *
+ * @param name Description of the Parameter
+ */
+ public AntCallBackTest( String name ) {
+ super( name );
+ }
+
+
+ /** The JUnit setup method */
+ public void setUp() {
+ configureProject( "test/resources/logic/antcallbacktest.xml" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test1() {
+ expectPropertySet( "test1", "prop1", "prop1" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test2() {
+ expectPropertySet( "test2", "prop1", "prop1" );
+ expectPropertySet( "test2", "prop2", "prop2" );
+ expectPropertySet( "test2", "prop3", "prop3" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test3() {
+ expectPropertySet( "test3", "prop1", "prop1" );
+ expectPropertySet( "test3", "prop2", "prop2" );
+ expectPropertySet( "test3", "prop3", "prop3" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test4() {
+ expectPropertyUnset( "test4", "prop1" );
+ expectPropertySet( "test4", "prop2", "prop2" );
+ expectPropertySet( "test4", "prop3", "prop3" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test5() {
+ expectPropertySet( "test5", "prop1", "blah" );
+ expectPropertySet( "test5", "prop2", "prop2" );
+ expectPropertySet( "test5", "prop3", "prop3" );
+ }
+}
+
diff --git a/test/src/net/sf/antcontrib/logic/AssertTest.java b/test/src/net/sf/antcontrib/logic/AssertTest.java
new file mode 100644
index 0000000..449068f
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/AssertTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+/**
+ * Since AntCallBack is basically a copy and paste of antcall, the only testing
+ * done here is on the extra features provided by antcallback. It is assumed
+ * that changes to antcall will be propagated to antcallback and that antcall
+ * has it's own unit tests (which turns out to have been a bad assumption,
+ * I can't find any unit tests for antcall).
+ *
+ * @author danson
+ */
+public class AssertTest extends BuildFileTestBase {
+
+ /**
+ * Constructor for the AntCallBackTest object
+ *
+ * @param name Description of the Parameter
+ */
+ public AssertTest( String name ) {
+ super( name );
+ }
+
+
+ /** The JUnit setup method */
+ public void setUp() {
+ configureProject( "test/resources/logic/asserttest.xml" );
+ }
+
+
+ /** A unit test for JUnit */
+ public void test1() {
+ executeTarget( "test1" );
+ }
+
+ public void test2() {
+ expectBuildExceptionStackTraceContaining( "test2", "testing assert failure", "Property 'testprop' doesn't exist in this project." );
+ }
+
+ public void test3() {
+ expectBuildExceptionStackTraceContaining( "test3", "testing assert failure", "Expected 'false', but was 'true'." );
+ }
+
+ public void test4() {
+ executeTarget("test4");
+ }
+
+ public void test5() {
+ executeTarget("test5");
+ }
+
+ public void test6() {
+ executeTarget("test6");
+ }
+
+ public void test7(){
+ expectBuildExceptionStackTraceContaining( "test7", "testing conditions", "Assertion failed boolean test." );
+ }
+
+ public void test8() {
+ executeTarget("test8");
+ }
+
+ public void test9() {
+ expectBuildExceptionStackTraceContaining( "test9", "testing conditions", "Assertion failed boolean test." );
+ }
+}
+
diff --git a/test/src/net/sf/antcontrib/logic/ForeachTaskTest.java b/test/src/net/sf/antcontrib/logic/ForeachTaskTest.java
new file mode 100644
index 0000000..b02e453
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/ForeachTaskTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <foreach>.
+ */
+public class ForeachTaskTest extends BuildFileTest {
+
+ public ForeachTaskTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/foreach.xml");
+ }
+
+ public void tearDown() {
+ executeTarget("teardown");
+ }
+
+ public void testSimpleList() {
+ simpleTest("simpleList");
+ }
+
+ public void testDelimiter() {
+ simpleTest("delimiter");
+ }
+
+ public void testFileset() {
+ simpleTest("fileset");
+ assertTrue(getLog().indexOf("The nested fileset element is deprectated,"
+ + " use a nested path instead") > -1);
+ }
+
+ public void testFilesetAndList() {
+ simpleTest("filesetAndList");
+ assertTrue(getLog().indexOf("The nested fileset element is deprectated,"
+ + " use a nested path instead") > -1);
+ }
+
+ public void testNoList() {
+ expectSpecificBuildException("noList", "neither list nor fileset",
+ "You must have a list or path to iterate through");
+ }
+
+ public void testNoTarget() {
+ expectSpecificBuildException("noTarget", "no target",
+ "You must supply a target to perform");
+ }
+
+ public void testNoParam() {
+ expectSpecificBuildException("noParam", "no param",
+ "You must supply a property name to set on each iteration in param");
+ }
+
+ public void testNestedParam() {
+ executeTarget("nestedParam");
+ assertTrue(getLog().indexOf("Called with param: rincewind") > -1);
+ }
+
+ public void testNestedReference() {
+ executeTarget("nestedReference");
+ assertTrue(getLog().indexOf("Called with param: twoflower") > -1);
+ }
+
+ public void testPath() {
+ simpleTest("path");
+ }
+
+ public void testPathAndList() {
+ simpleTest("pathAndList");
+ }
+
+ private void simpleTest(String target) {
+ executeTarget(target);
+ int last = -1;
+ for (int i = 1; i < 4; i++) {
+ int thisIdx = getLog().indexOf("Called with param: " + i);
+ assertTrue(thisIdx > last);
+ last = thisIdx;
+ }
+ }
+}
diff --git a/test/src/net/sf/antcontrib/logic/IfTaskTest.java b/test/src/net/sf/antcontrib/logic/IfTaskTest.java
new file mode 100644
index 0000000..bac8aff
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/IfTaskTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <if>.
+ */
+public class IfTaskTest extends BuildFileTest {
+
+ public IfTaskTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/if.xml");
+ }
+
+ public void testNoCondition() {
+ expectSpecificBuildException("noCondition", "no condition",
+ "You must nest a condition into <if>");
+ }
+
+ public void testTwoConditions() {
+ expectSpecificBuildException("twoConditions", "two conditions",
+ "You must not nest more than one "
+ + "condition into <if>");
+ }
+
+ public void testNothingToDo() {
+ expectLog("nothingToDo", "");
+ }
+
+ public void testTwoThens() {
+ expectSpecificBuildException("twoThens", "two <then>s",
+ "You must not nest more than one "
+ + "<then> into <if>");
+ }
+
+ public void testTwoElses() {
+ expectSpecificBuildException("twoElses", "two <else>s",
+ "You must not nest more than one "
+ + "<else> into <if>");
+ }
+
+ public void testNormalOperation() {
+ executeTarget("normalOperation");
+ assertTrue(getLog().indexOf("In then") > -1);
+ assertTrue(getLog().indexOf("some value") > -1);
+ assertEquals(-1, getLog().indexOf("${inner}"));
+ assertEquals(-1, getLog().indexOf("In else"));
+ }
+
+ public void testNormalOperation2() {
+ executeTarget("normalOperation2");
+ assertTrue(getLog().indexOf("In else") > -1);
+ assertEquals(-1, getLog().indexOf("In then"));
+ }
+
+ public void testNoConditionInElseif() {
+ expectSpecificBuildException("noConditionInElseif", "no condition",
+ "You must nest a condition into <elseif>");
+ }
+
+ public void testTwoConditionInElseif() {
+ expectSpecificBuildException("twoConditionsInElseif", "two conditions",
+ "You must not nest more than one "
+ + "condition into <elseif>");
+ }
+
+ public void testNormalOperationElseif() {
+ executeTarget("normalOperationElseif");
+ assertTrue(getLog().indexOf("In elseif") > -1);
+ assertEquals(-1, getLog().indexOf("In then"));
+ assertEquals(-1, getLog().indexOf("In else-branch"));
+ }
+
+ public void testNormalOperationElseif2() {
+ executeTarget("normalOperationElseif2");
+ assertTrue(getLog().indexOf("In else-branch") > -1);
+ assertEquals(-1, getLog().indexOf("In then"));
+ assertEquals(-1, getLog().indexOf("In elseif"));
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/logic/OutOfDateTest.java b/test/src/net/sf/antcontrib/logic/OutOfDateTest.java
new file mode 100644
index 0000000..ae52caa
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/OutOfDateTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildFileTest;
+import org.apache.tools.ant.types.Path;
+
+/**
+ * Testcase for <outofdate>.
+ *
+ * @author Peter Reilly
+ */
+public class OutOfDateTest extends BuildFileTest {
+
+ public OutOfDateTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/outofdate.xml");
+ }
+
+ public void tearDown() {
+ executeTarget("cleanup");
+ }
+
+ public void testSimple() {
+ executeTarget("simple");
+ }
+
+ public void testVerbose() {
+ executeTarget("verbose");
+ assertTrue(getLog().indexOf("outofdate with regard to") > -1);
+ }
+
+ public void testDelete() {
+ executeTarget("delete");
+ }
+
+ public void testDeleteAll() {
+ executeTarget("delete-all");
+ }
+
+ public void testDeleteQuiet() {
+ executeTarget("init");
+ executeTarget("delete-quiet");
+ assertTrue("No deleting message", getLog().indexOf("Deleting") == -1);
+ }
+
+ public void testFileset() {
+ executeTarget("outofdate.init");
+ executeTarget("outofdate.test");
+ assertTrue(getLog().indexOf("outofdate triggered") > -1);
+ String outofdateSources =
+ getProject().getProperty("outofdate.sources");
+ // switch \ to / if present
+ outofdateSources.replace('\\', '/');
+ assertTrue("newer.text empty", outofdateSources.indexOf(
+ "newer.text") > -1);
+ assertTrue("file.notdone", outofdateSources.indexOf(
+ "outofdate/source/1/2/file.notdone") > -1);
+ assertTrue("file.done", outofdateSources.indexOf(
+ "outofdate/source/1/2/file.done") == -1);
+ assertTrue("done.y", outofdateSources.indexOf(
+ "outofdate/source/1/done.y") == -1);
+ assertTrue("partial.y", outofdateSources.indexOf(
+ "outofdate/source/1/partial.y") > -1);
+ String outofdateTargets =
+ getProject().getProperty("outofdate.targets");
+ assertTrue(outofdateTargets.indexOf(
+ "outofdate.xml") > -1);
+ assertTrue(outofdateTargets.indexOf(
+ "outofdate/gen/1/2/file.notdone") > -1);
+ assertTrue(outofdateTargets.indexOf(
+ "outofdate/gen/1/partial.h") > -1);
+ assertTrue(outofdateTargets.indexOf(
+ "outofdate/gen/1/partial.c") == -1);
+ assertTrue(outofdateTargets.indexOf(
+ "outofdate/gen/1/done.h") == -1);
+
+ Path sourcesPath = (Path) getProject().getReference(
+ "outofdate.sources.path");
+ assertTrue(sourcesPath != null);
+ String[] sources = sourcesPath.list();
+ assertTrue(sources.length == 3);
+ Path targetsPath = (Path) getProject().getReference(
+ "outofdate.targets.path");
+ String[] targets = targetsPath.list();
+ assertTrue(targetsPath != null);
+ assertTrue(targets.length == 3);
+ }
+
+ public void testEmptySources() {
+ executeTarget("empty-sources");
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/logic/SwitchTest.java b/test/src/net/sf/antcontrib/logic/SwitchTest.java
new file mode 100644
index 0000000..28ce036
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/SwitchTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <switch>.
+ */
+public class SwitchTest extends BuildFileTest {
+
+ public SwitchTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/switch.xml");
+ }
+
+ public void testNoValue() {
+ expectSpecificBuildException("noValue", "no value",
+ "Value is missing");
+ }
+
+ public void testNoChildren() {
+ expectSpecificBuildException("noChildren", "no children",
+ "No cases supplied");
+ }
+
+ public void testTwoDefaults() {
+ expectSpecificBuildException("twoDefaults", "two defaults",
+ "Cannot specify multiple default cases");
+ }
+
+ public void testNoMatch() {
+ expectSpecificBuildException("noMatch", "no match",
+ "No case matched the value foo"
+ + " and no default has been specified.");
+ }
+
+ public void testCaseNoValue() {
+ expectSpecificBuildException("caseNoValue", "<case> no value",
+ "Value is required for case.");
+ }
+
+ public void testDefault() {
+ executeTarget("testDefault");
+ assertTrue(getLog().indexOf("In default") > -1);
+ assertTrue(getLog().indexOf("baz") > -1);
+ assertEquals(-1, getLog().indexOf("${inner}"));
+ assertEquals(-1, getLog().indexOf("In case"));
+ }
+
+ public void testCase() {
+ executeTarget("testCase");
+ assertTrue(getLog().indexOf("In case") > -1);
+ assertTrue(getLog().indexOf("baz") > -1);
+ assertEquals(-1, getLog().indexOf("${inner}"));
+ assertEquals(-1, getLog().indexOf("In default"));
+ }
+
+ public void testCaseSensitive() {
+ executeTarget("testCaseSensitive");
+ assertTrue(getLog().indexOf("In default") > -1);
+ assertEquals(-1, getLog().indexOf("In case"));
+ }
+
+ public void testCaseInSensitive() {
+ executeTarget("testCaseInSensitive");
+ assertTrue(getLog().indexOf("In case") > -1);
+ assertEquals(-1, getLog().indexOf("In default"));
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/logic/ThrowTaskTest.java b/test/src/net/sf/antcontrib/logic/ThrowTaskTest.java
new file mode 100644
index 0000000..1ad32e6
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/ThrowTaskTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <throw>.
+ */
+public class ThrowTaskTest extends BuildFileTest {
+
+ public ThrowTaskTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/throw.xml");
+ }
+
+ public void testRefid() {
+ String message = "exception created by testcase";
+ getProject().addReference("testref", new BuildException(message));
+ expectSpecificBuildException("useRefid", "this is what we've put in",
+ message);
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/logic/TimestampSelectorTest.java b/test/src/net/sf/antcontrib/logic/TimestampSelectorTest.java
new file mode 100644
index 0000000..601c8be
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/TimestampSelectorTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <foreach>.
+ */
+public class TimestampSelectorTest extends BuildFileTest {
+
+ public TimestampSelectorTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/timestampselector.xml");
+ }
+
+ public void tearDown() {
+ executeTarget("teardown");
+ }
+
+ public void testFileStampFL() {
+ simpleTest("filestamp.fl", "file2.txt");
+ }
+
+ public void testFileStampPR() {
+ simpleTest("filestamp.pr", "file2.txt");
+ }
+
+ public void testDirStampDL() {
+ simpleTest("dirstamp.dl", "dir2");
+ }
+
+ public void testDirStampPR() {
+ simpleTest("dirstamp.pr", "dir2");
+ }
+
+ private void simpleTest(String target, String expected)
+ {
+ executeTarget(target);
+ assertTrue(getLog().indexOf(expected) > -1);
+ }
+}
diff --git a/test/src/net/sf/antcontrib/logic/TryCatchTaskTest.java b/test/src/net/sf/antcontrib/logic/TryCatchTaskTest.java
new file mode 100644
index 0000000..feb8999
--- /dev/null
+++ b/test/src/net/sf/antcontrib/logic/TryCatchTaskTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2001-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.logic;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <trycatch>.
+ */
+public class TryCatchTaskTest extends BuildFileTest {
+
+ public TryCatchTaskTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/trycatch.xml");
+ }
+
+ public void testFullTest() {
+ executeTarget("fullTest");
+ assertEquals("Tada!", getProject().getProperty("foo"));
+ Object e = getProject().getReference("bar");
+ assertNotNull(e);
+ assertTrue(e instanceof BuildException);
+ assertEquals("Tada!", ((BuildException) e).getMessage());
+ }
+
+ public void testTwoCatches() {
+ // two catch blocks were not supported prior to TryCatchTask.java v 1.4.
+ executeTarget("twoCatches");
+ }
+
+ public void testTwoFinallys() {
+ expectSpecificBuildException("twoFinallys", "two finally children",
+ "You must not specify more than one <finally>");
+ }
+
+ public void testTwoTrys() {
+ expectSpecificBuildException("twoTrys", "two try children",
+ "You must not specify more than one <try>");
+ }
+
+ public void testNoTry() {
+ expectSpecificBuildException("noTry", "no try child",
+ "A nested <try> element is required");
+ }
+
+ public void testNoException() {
+ executeTarget("noException");
+ int message = getLog().indexOf("Tada!");
+ int catchBlock = getLog().indexOf("In <catch>");
+ int finallyBlock = getLog().indexOf("In <finally>");
+ assertTrue(message > -1);
+ assertEquals(-1, catchBlock);
+ assertTrue(finallyBlock > message);
+ assertNull(getProject().getProperty("foo"));
+ assertNull(getProject().getReference("bar"));
+ }
+}
+
diff --git a/test/src/net/sf/antcontrib/math/MathTest.java b/test/src/net/sf/antcontrib/math/MathTest.java
new file mode 100644
index 0000000..aba9d17
--- /dev/null
+++ b/test/src/net/sf/antcontrib/math/MathTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.math;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+/**
+ *
+ * @author danson
+ */
+public class MathTest extends BuildFileTestBase {
+
+ /**
+ * Constructor for the MathTest object
+ *
+ * @param name Description of the Parameter
+ */
+ public MathTest( String name ) {
+ super( name );
+ }
+
+ /** The JUnit setup method */
+ public void setUp() {
+ configureProject( "test/resources/math/mathtest.xml" );
+ }
+
+ /** A unit test for JUnit */
+ public void test1() {
+ expectPropertySet("test1", "result", "18");
+ }
+}
+
diff --git a/test/src/net/sf/antcontrib/platform/OsFamilyTest.java b/test/src/net/sf/antcontrib/platform/OsFamilyTest.java
new file mode 100644
index 0000000..9dbd237
--- /dev/null
+++ b/test/src/net/sf/antcontrib/platform/OsFamilyTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.platform;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <osfamily>.
+ */
+public class OsFamilyTest extends BuildFileTest {
+
+ public OsFamilyTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/platform/osfamily.xml");
+ }
+
+ public void testConsistency() {
+ executeTarget("consistency");
+ assertPropertyEquals("consistent", "true");
+ }
+
+ public void testMissingProperty() {
+ expectSpecificBuildException("missingProperty", "no attribute",
+ "The attribute 'property' is required "
+ + "for the OsFamily task.");
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/platform/ShellScriptTest.java b/test/src/net/sf/antcontrib/platform/ShellScriptTest.java
new file mode 100644
index 0000000..ba1a30e
--- /dev/null
+++ b/test/src/net/sf/antcontrib/platform/ShellScriptTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.platform;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <shellscript>
+ *
+ * @author Peter Reilly
+ */
+public class ShellScriptTest extends BuildFileTest {
+ public ShellScriptTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/platform/shellscript.xml");
+ staticInitialize();
+ }
+
+ public void testShHello() {
+ if (! hasSh)
+ return;
+ executeTarget("sh.hello");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testBashHello() {
+ if (! hasBash)
+ return;
+ executeTarget("bash.hello");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testShInputString() {
+ if (! hasSh)
+ return;
+ executeTarget("sh.inputstring");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testShProperty() {
+ if (! hasSh)
+ return;
+ executeTarget("sh.property");
+ assertTrue(getLog().indexOf("this is a property") > -1);
+ }
+
+
+ public void testPythonHello() {
+ if (! hasPython)
+ return;
+ executeTarget("python.hello");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testPerlHello() {
+ if (! hasPerl)
+ return;
+ executeTarget("perl.hello");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testNoShell() {
+ expectBuildExceptionContaining(
+ "noshell", "Execute failed", "a shell that should not exist");
+ }
+
+ public void testSed() {
+ if (! hasSed)
+ return;
+ executeTarget("sed.test");
+ assertTrue(getLog().indexOf("BAR bar bar bar BAR bar") > -1);
+ }
+
+ public void testSetProperty() {
+ if (! hasSh)
+ return;
+ executeTarget("sh.set.property");
+ assertPropertyEquals("sh.set.property", "hello world");
+ }
+
+ public void testTmpSuffix() {
+ if (! hasSh)
+ return;
+ executeTarget("sh.tmp.suffix");
+ assertTrue(getLog().indexOf(".bat") > -1);
+ }
+
+ public void testCmd() {
+ if (! hasCmd)
+ return;
+ executeTarget("cmd.test");
+ assertTrue(getLog().indexOf("hello world") > -1);
+ }
+
+ public void testDir() {
+ if (! hasBash)
+ return;
+ executeTarget("dir.test");
+ assertTrue(
+ getProject().getProperty("dir.test.property")
+ .indexOf("subdir") > -1);
+ }
+
+ public void testCommand() {
+ expectBuildExceptionContaining(
+ "command.test", "Attribute failed",
+ "Attribute command is not supported");
+ }
+
+ private static boolean initialized = false;
+ private static boolean hasSh = false;
+ private static boolean hasBash = false;
+ private static boolean hasPython = false;
+ private static boolean hasPerl = false;
+ private static boolean hasSed = false;
+ private static boolean hasCmd = false;
+ private static Object staticMonitor = new Object();
+
+ /**
+ * check if the env contains the shells
+ * sh, bash, python and perl
+ * assume cmd.exe exists for windows
+ */
+ private void staticInitialize() {
+ synchronized (staticMonitor) {
+ if (initialized)
+ return;
+ initialized = true;
+ hasSh = hasShell("hassh");
+ hasBash = hasShell("hasbash");
+ hasPerl = hasShell("hasperl");
+ hasPython = hasShell("haspython");
+ hasSed = hasShell("hassed");
+ hasCmd = hasShell("hascmd");
+
+ }
+ }
+
+ private boolean hasShell(String target) {
+ try {
+ executeTarget(target);
+ return true;
+ }
+ catch (Throwable t) {
+ return false;
+ }
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/process/LimitTest.java b/test/src/net/sf/antcontrib/process/LimitTest.java
new file mode 100644
index 0000000..2e84dbd
--- /dev/null
+++ b/test/src/net/sf/antcontrib/process/LimitTest.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.process;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+public class LimitTest extends BuildFileTestBase {
+
+ public LimitTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/logic/limittest.xml");
+ }
+
+ public void test1() {
+ expectLogNotContaining("test1", "_failed_");
+ }
+
+ public void test2() {
+ expectLogContaining("test2", "_passed_");
+ }
+}
diff --git a/test/src/net/sf/antcontrib/property/PathToFileSetTest.java b/test/src/net/sf/antcontrib/property/PathToFileSetTest.java
new file mode 100644
index 0000000..da4a5d4
--- /dev/null
+++ b/test/src/net/sf/antcontrib/property/PathToFileSetTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <pathtofileset>.
+ */
+public class PathToFileSetTest extends BuildFileTest {
+
+ public PathToFileSetTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/property/pathtofileset.xml");
+ }
+
+ public void tearDown() {
+ executeTarget("cleanup");
+ }
+
+ public void testSimple() {
+ executeTarget("simple");
+ assertPropertyContains("simple.0.property", "0.java");
+ assertPropertyContains("simple.0.property", "1.java");
+ assertPropertyNotContains("simple.0.property", "2.java");
+ assertPropertyNotContains("simple.0.property", "3.java");
+ assertPropertyNotContains("simple.1.property", "0.java");
+ assertPropertyNotContains("simple.1.property", "1.java");
+ assertPropertyContains("simple.1.property", "2.java");
+ assertPropertyContains("simple.1.property", "3.java");
+ }
+
+ public void testSimpleException() {
+ expectBuildExceptionContaining("simple-exception", "expect not relative to",
+ "is not relative to");
+ }
+
+ private void assertPropertyContains(String property, String expected) {
+ String result = getProject().getProperty(property);
+ assertTrue("property " + property + " contains " + expected,
+ result.indexOf(expected) != -1);
+ }
+
+ private void assertPropertyNotContains(String property, String expected) {
+ String result = getProject().getProperty(property);
+ assertTrue("property " + property + " contains " + expected,
+ result.indexOf(expected) == -1);
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/property/PropertyCopyTest.java b/test/src/net/sf/antcontrib/property/PropertyCopyTest.java
new file mode 100644
index 0000000..c2d23dc
--- /dev/null
+++ b/test/src/net/sf/antcontrib/property/PropertyCopyTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <propertycopy>.
+ */
+public class PropertyCopyTest extends BuildFileTest {
+
+ public PropertyCopyTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/property/propertycopy.xml");
+ }
+
+ /**
+ * Runs a propertyCopy without a specified name attribute.
+ */
+ public void testMissingName() {
+ expectSpecificBuildException("missingName", "missing name",
+ "You must specify a property to set.");
+ }
+
+ public void testMissingFrom() {
+ expectSpecificBuildException("missingFrom", "missing from",
+ "Missing the 'from' attribute.");
+ }
+
+ public void testNonSilent() {
+ expectSpecificBuildException("nonSilent", "from doesn't exist",
+ "Property 'bar' is not defined.");
+ }
+
+ public void testSilent() {
+ executeTarget("silent");
+ assertPropertyEquals("foo", null);
+ }
+
+ public void testNormal() {
+ executeTarget("normal");
+ assertPropertyEquals("displayName", "My Organiziation");
+ }
+}
diff --git a/test/src/net/sf/antcontrib/property/PropertySelectorTest.java b/test/src/net/sf/antcontrib/property/PropertySelectorTest.java
new file mode 100644
index 0000000..16ad269
--- /dev/null
+++ b/test/src/net/sf/antcontrib/property/PropertySelectorTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2001-2005 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import org.apache.tools.ant.BuildFileTest;
+
+/**
+ * Testcase for <propertyselector>.
+ */
+public class PropertySelectorTest extends BuildFileTest {
+
+ public PropertySelectorTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/property/propertyselector.xml");
+ }
+
+ public void testDefaultGrouping() {
+ simpleTest("select.test.grouping.0",
+ "module.Module1.id", "module.Module2.id");
+ }
+
+ public void testDefaultGrouping1() {
+ simpleTest("select.test.grouping.1",
+ "Module1", "Module2");
+ }
+
+ private void simpleTest(String target, String expected1, String expected2)
+ {
+ executeTarget(target);
+ String order1 = expected1 + "," + expected2;
+ String order2 = expected2 + "," + expected1;
+ int index1 = getLog().indexOf(order1);
+ int index2 = getLog().indexOf(order2);
+ assertTrue("Neither '" + order1 + "' nor '" + order2
+ + "' was found in '" + getLog() + "'",
+ index1 > -1 || index2 > -1);
+ }
+
+}
diff --git a/test/src/net/sf/antcontrib/property/VariableTest.java b/test/src/net/sf/antcontrib/property/VariableTest.java
new file mode 100644
index 0000000..d54c111
--- /dev/null
+++ b/test/src/net/sf/antcontrib/property/VariableTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.property;
+
+import net.sf.antcontrib.BuildFileTestBase;
+
+
+public class VariableTest extends BuildFileTestBase {
+
+ public VariableTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+ configureProject("test/resources/property/variabletest.xml");
+ }
+
+ public void test1() {
+ expectPropertySet("test1", "x", "6");
+ }
+
+ public void test2() {
+ expectPropertySet("test2", "x", "12");
+ }
+
+ public void test3() {
+ expectPropertySet("test3", "x", "6 + 12");
+ }
+
+ public void test4() {
+ expectPropertySet("test4", "x", "6");
+ }
+
+ public void test5() {
+ expectPropertySet("test5", "str", "I am a string.");
+ }
+
+ public void test6() {
+ expectPropertySet("test6", "x", "Today is blue.");
+ }
+
+ public void test7() {
+ expectPropertySet("test7", "x", "6");
+ }
+
+ /* TODO: depends on the Antelope <if>, need to adjust to use the ant-contrib <if>
+ public void test8() {
+ expectPropertySet("test8", "x", "12");
+ expectLogContaining("test8", "12");
+ }
+ */
+ public void test9() {
+ expectPropertyUnset("test9", "i");
+ }
+
+ public void test10() {
+ expectPropertySet("test10", "x", "xxx");
+ }
+}
diff --git a/test/src/net/sf/antcontrib/walls/CompileWithWallsTest.java b/test/src/net/sf/antcontrib/walls/CompileWithWallsTest.java
new file mode 100644
index 0000000..fe6a203
--- /dev/null
+++ b/test/src/net/sf/antcontrib/walls/CompileWithWallsTest.java
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package net.sf.antcontrib.walls;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildFileTest;
+
+import junit.framework.TestSuite;
+import junit.textui.TestRunner;
+
+/**
+ * BIG NOTE***************************************************
+ * Always expect specific exceptions. Most of these test cases when
+ * first submitted were not and therefore were not testing what they said
+ * they were testing. Exceptions were being caused by other things and the
+ * tests were still passing. Now all tests expect a specific exception
+ * so if any other is thrown we will fail the test case.
+ * ************************************************************
+ *
+ * Testcase for <propertycopy>.
+ */
+public class CompileWithWallsTest extends BuildFileTest {
+
+ private String baseDir = "test"+File.separator
+ +"resources"+File.separator
+ +"walls"+File.separator;
+ private String c = File.separator;
+
+ public CompileWithWallsTest(String name) {
+ super(name);
+ }
+
+ public void setUp() {
+
+ configureProject("test/resources/walls/compilewithwalls.xml");
+// project.addBuildListener(new LogListener());
+ }
+// protected class LogListener implements BuildListener {
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#buildStarted(org.apache.tools.ant.BuildEvent)
+// */
+// public void buildStarted(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#buildFinished(org.apache.tools.ant.BuildEvent)
+// */
+// public void buildFinished(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#targetStarted(org.apache.tools.ant.BuildEvent)
+// */
+// public void targetStarted(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#targetFinished(org.apache.tools.ant.BuildEvent)
+// */
+// public void targetFinished(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#taskStarted(org.apache.tools.ant.BuildEvent)
+// */
+// public void taskStarted(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#taskFinished(org.apache.tools.ant.BuildEvent)
+// */
+// public void taskFinished(BuildEvent event) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// /* (non-Javadoc)
+// * @see org.apache.tools.ant.BuildListener#messageLogged(org.apache.tools.ant.BuildEvent)
+// */
+// public void messageLogged(BuildEvent event) {
+//
+// System.out.println(event.getException());
+// System.out.println("aaa");
+// }
+//
+// }
+
+ public void tearDown() {
+ executeTarget("cleanup");
+
+// System.out.println(getFullLog());
+// System.out.println("std out. from ant build begin--------------");
+// System.out.println(getOutput());
+// System.out.println("std.out. from ant build end----------------");
+// System.out.println("std err. from ant build begin--------------");
+// System.out.println(getError());
+// System.out.println("std.err. from ant build end----------------");
+ }
+
+ public void testTooManyNestedWallElements() {
+ expectSpecificBuildException("testTooManyNestedWallElements"
+ , "TooManyNestedWallElements"
+ , "compilewithwalls task only supports one nested walls element or one walls attribute");
+ }
+
+ public void testFakeTest() {
+ //this is being deprecated, tests no longer really needed.
+ }
+// public void testTooManyNestedJavacElements() {
+// expectSpecificBuildException("testTooManyNestedJavacElements"
+// , "TooManyNestedJavacElements"
+// , "compilewithwalls task only supports one nested javac element");
+// }
+//
+// public void testNoWallElement() {
+// expectSpecificBuildException("testNoWallElement"
+// , "NoWallElement"
+// , "There must be a nested walls element");
+// }
+//
+// public void testNoJavacElement() {
+// expectSpecificBuildException("testNoJavacElement"
+// , "NoJavacElement"
+// , "There must be a nested javac element");
+// }
+//
+// public void testMoreThanOneSrcDirInJavac() {
+// executeTarget("testMoreThanOneSrcDirInJavac");
+// }
+//
+// public void testNoSrcDirInJavac() {
+// expectSpecificBuildException("testNoSrcDirInJavac"
+// , "NoSrcDirInJavac"
+// , "Javac inside compilewithwalls must have a srcdir specified");
+// }
+//
+// public void testIntermediaryDirAndDestDirSame() {
+// expectSpecificBuildException("testIntermediaryDirAndDestDirSame"
+// , "IntermediaryDirAndDestDirSame"
+// , "intermediaryBuildDir attribute cannot be specified\n"
+// +"to be the same as destdir or inside desdir of the javac task.\n"
+// +"This is an intermediary build directory only used by the\n"
+// +"compilewithwalls task, not the class file output directory.\n"
+// +"The class file output directory is specified in javac's destdir attribute");
+// }
+//
+// public void testIntermediaryDirInsideDestDir() {
+// expectSpecificBuildException("testIntermediaryDirInsideDestDir"
+// , "IntermediaryDirInsideDestDir"
+// , "intermediaryBuildDir attribute cannot be specified\n"
+// +"to be the same as destdir or inside desdir of the javac task.\n"
+// +"This is an intermediary build directory only used by the\n"
+// +"compilewithwalls task, not the class file output directory.\n"
+// +"The class file output directory is specified in javac's destdir attribute");
+// }
+//
+// public void testPackageDoesntEndWithStar() {
+// expectSpecificBuildException("testPackageDoesntEndWithStar"
+// , "PackageDoesntEndWithStar"
+// , "The package='biz.xsoftware' must end with "
+// + ".* or .** such as biz.xsoftware.* or "
+// + "biz.xsoftware.**" );
+// }
+//
+// public void testPackageDoesntHaveSlash() {
+// expectSpecificBuildException("testPackageDoesntHaveSlash"
+// , "PackageDoesntHaveSlash"
+// ,"A package name cannot contain '\\' or '/' like package="
+// + "biz/xsoftware.*\nIt must look like biz.xsoftware.* for example");
+// }
+//
+// public void testDependsOnNonExistPackage() {
+// expectSpecificBuildException("testDependsOnNonExistPackage"
+// , "DependsOnNonExistPackage"
+// , "package name=modA did not have modB"
+// + " listed before it and cannot compile without it");
+// }
+//
+// public void testDependsOnPackageAfter() {
+// expectSpecificBuildException("testDependsOnPackageAfter"
+// , "DependsOnPackageAfter"
+// , "package name=modA did not have modB"
+// + " listed before it and cannot compile without it");
+// }
+//
+// public void testPackageABreakingWhenAIsCompiledFirst() {
+// expectSpecificBuildException("testPackageABreakingWhenAIsCompiledFirst"
+// , "PackageABreakingWhenAIsCompiledFirst"
+// , "Compile failed; see the compiler error output for details.");
+// }
+//
+//
+// /**
+// * This test case tests when modB depends on modA but it was
+// * not specified in the walls so modA is not in modB's path.
+// * The build should then fail until they change the build.xml
+// * so modB depends on modA in the walls element.
+// */
+// public void testPackageBBreakingWhenAIsCompiledFirst() {
+//
+// expectSpecificBuildException("testPackageBBreakingWhenAIsCompiledFirst"
+// , "PackageBBreakingWhenAIsCompiledFirst"
+// , "Compile failed; see the compiler error output for details.");
+//
+// //modA should have been compiled successfully, it is only modB that
+// //fails. It is very important we make sure A got compiled otherwise
+// //we are not testing the correct behavior and the test would be wrong.
+// ensureClassFileExists("testB"+c+"mod"+c+"modA"+c+"ModuleA.class", true);
+// ensureClassFileExists("testB"+c+"mod"+c+"modB"+c+"ModuleB.class", false);
+// }
+//
+// public void testCompileOfAllUsingDepends() {
+// ensureClassFileExists("testC"+c+"mod"+c+"Module.class", false);
+// //make sure we are testing the correct thing and Module.java exists!
+// ensureJavaFileExists("testC"+c+"mod"+c+"Module.java", true);
+//
+// executeTarget("testCompileOfAllUsingDepends");
+//
+// //must test class files were actually created afterwards.
+// //The build might pass with no class files if the task is
+// //messed up.
+// ensureClassFileExists("testC"+c+"mod"+c+"Module.class", true);
+//
+// }
+////---------------------------------------------------------
+////
+//// The following tests are all just repeats of some of the above tests
+//// except the below tests use External walls file and the above tests
+//// don't.
+////
+////---------------------------------------------------------
+//
+// public void testDependsOnPackageAfterExternalWalls() {
+// expectSpecificBuildException("testDependsOnPackageAfterExternalWalls"
+// , "DependsOnPackageAfterExternalWalls"
+// , "package name=modA did not have modB"
+// + " listed before it and cannot compile without it");
+// }
+//
+// /**
+// * This test case tests when modB depends on modA but it was
+// * not specified in the walls so modA is not in modB's path.
+// * The build should then fail until they change the build.xml
+// * so modB depends on modA in the walls element.
+// */
+// public void testPackageBBreakingWhenAIsCompiledFirstExternalWalls() {
+// ensureClassFileExists("testB"+c+"mod"+c+"modA"+c+"ModuleA.class", false);
+// ensureJavaFileExists("testB"+c+"mod"+c+"modB"+c+"ModuleB.java", true);
+//
+// expectSpecificBuildException("testPackageBBreakingWhenAIsCompiledFirst"
+// , "PackageBBreakingWhenAIsCompiledFirst"
+// , "Compile failed; see the compiler error output for details.");
+//
+// //modA should have been compiled successfully, it is only modB that
+// //fails. It is very important we make sure A got compiled otherwise
+// //we are not testing the correct behavior and the test would be wrong.
+// ensureClassFileExists("testB"+c+"mod"+c+"modA"+c+"ModuleA.class", true);
+// ensureClassFileExists("testB"+c+"mod"+c+"modB"+c+"ModuleB.class", false);
+// }
+//
+// public void testCompileOfAllUsingDependsExternalWalls() {
+// ensureClassFileExists("testC"+c+"mod"+c+"Module.class", false);
+// ensureJavaFileExists("testC"+c+"mod"+c+"Module.java", true);
+// executeTarget("testCompileOfAllUsingDependsExternalWalls");
+// //must test class files were actually created afterwards.
+// //The build might pass with no class files if the task is
+// //messed up.
+// ensureClassFileExists("testC"+c+"mod"+c+"Module.class", true);
+// }
+
+ private void ensureJavaFileExists(String file, boolean shouldExist) {
+
+ //must test that it is testing the correct directory.
+ //It wasn't before.
+ String javaFile = baseDir+file;
+ File f1 = new File(javaFile);
+ if(shouldExist)
+ assertTrue("The java file="+f1.getAbsolutePath()+" didn't exist, we can't run this test. It will pass with false results",
+ f1.exists());
+ else
+ assertTrue("The java file="+f1.getAbsolutePath()+" exists and shouldn't, we can't run this test. It will pass with false results",
+ !f1.exists());
+ }
+
+ private void ensureClassFileExists(String file, boolean shouldExist) {
+
+ String classFile = baseDir
+ +"compilewithwalls"+File.separator
+ +"classes"+File.separator
+ +file;
+
+ File f1 = new File(classFile);
+ if(shouldExist)
+ assertTrue("The class file="+f1.getAbsolutePath()+" didn't get created, No build exception\nwas thrown, but the build failed because a class\nfile should have been created",
+ f1.exists());
+ else
+ assertTrue("The class file="+f1.getAbsolutePath()+" exists and shouldn't\nTest may be inaccurate if this file already exists...correct the test",
+ !f1.exists());
+ }
+
+ public static void main(String[] args) {
+ TestSuite suite = new TestSuite(CompileWithWallsTest.class);
+ TestRunner.run(suite);
+ }
+}
diff --git a/test/src/org/apache/tools/ant/BuildFileTest.java b/test/src/org/apache/tools/ant/BuildFileTest.java
new file mode 100644
index 0000000..0f950e7
--- /dev/null
+++ b/test/src/org/apache/tools/ant/BuildFileTest.java
@@ -0,0 +1,478 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.tools.ant;
+
+import junit.framework.TestCase;
+import org.apache.tools.ant.Project;
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URL;
+
+/**
+ * A BuildFileTest is a TestCase which executes targets from an Ant buildfile
+ * for testing.
+ *
+ * This class provides a number of utility methods for particular build file
+ * tests which extend this class.
+ *
+ */
+public abstract class BuildFileTest extends TestCase {
+
+ protected Project project;
+
+ private StringBuffer logBuffer;
+ private StringBuffer fullLogBuffer;
+ private StringBuffer outBuffer;
+ private StringBuffer errBuffer;
+ private BuildException buildException;
+
+ /**
+ * Constructor for the BuildFileTest object
+ *
+ *@param name string to pass up to TestCase constructor
+ */
+ public BuildFileTest(String name) {
+ super(name);
+ }
+
+ /**
+ * run a target, expect for any build exception
+ *
+ *@param target target to run
+ *@param cause information string to reader of report
+ */
+ protected void expectBuildException(String target, String cause) {
+ expectSpecificBuildException(target, cause, null);
+ }
+
+ /**
+ * Assert that only the given message has been logged with a
+ * priority &gt;= INFO when running the given target.
+ */
+ protected void expectLog(String target, String log) {
+ executeTarget(target);
+ String realLog = getLog();
+ assertEquals(log, realLog);
+ }
+
+ /**
+ * Assert that the given substring is in the log messages
+ */
+
+ protected void assertLogContaining(String substring) {
+ String realLog = getLog();
+ assertTrue("expecting log to contain \"" + substring + "\" log was \""
+ + realLog + "\"",
+ realLog.indexOf(substring) >= 0);
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority
+ * &gt;= INFO when running the given target.
+ */
+ protected void expectLogContaining(String target, String log) {
+ executeTarget(target);
+ assertLogContaining(log);
+ }
+
+ /**
+ * Gets the log the BuildFileTest object.
+ * only valid if configureProject() has
+ * been called.
+ * @pre logBuffer!=null
+ * @return The log value
+ */
+ protected String getLog() {
+ return logBuffer.toString();
+ }
+
+ /**
+ * Assert that the given message has been logged with a priority
+ * &gt;= DEBUG when running the given target.
+ */
+ protected void expectDebuglog(String target, String log) {
+ executeTarget(target);
+ String realLog = getFullLog();
+ assertEquals(log, realLog);
+ }
+
+ /**
+ * Gets the log the BuildFileTest object.
+ * only valid if configureProject() has
+ * been called.
+ * @pre fullLogBuffer!=null
+ * @return The log value
+ */
+ protected String getFullLog() {
+ return fullLogBuffer.toString();
+ }
+
+ /**
+ * execute the target, verify output matches expectations
+ *
+ *@param target target to execute
+ *@param output output to look for
+ */
+
+ protected void expectOutput(String target, String output) {
+ executeTarget(target);
+ String realOutput = getOutput();
+ assertEquals(output, realOutput.trim());
+ }
+
+ /**
+ * execute the target, verify output matches expectations
+ * and that we got the named error at the end
+ *@param target target to execute
+ *@param output output to look for
+ *@param error Description of Parameter
+ */
+
+ protected void expectOutputAndError(String target, String output, String error) {
+ executeTarget(target);
+ String realOutput = getOutput();
+ assertEquals(output, realOutput);
+ String realError = getError();
+ assertEquals(error, realError);
+ }
+
+ protected String getOutput() {
+ return cleanBuffer(outBuffer);
+ }
+
+ protected String getError() {
+ return cleanBuffer(errBuffer);
+ }
+
+ protected BuildException getBuildException() {
+ return buildException;
+ }
+
+ private String cleanBuffer(StringBuffer buffer) {
+ StringBuffer cleanedBuffer = new StringBuffer();
+ boolean cr = false;
+ for (int i = 0; i < buffer.length(); i++) {
+ char ch = buffer.charAt(i);
+ if (ch == '\r') {
+ cr = true;
+ continue;
+ }
+
+ if (!cr) {
+ cleanedBuffer.append(ch);
+ } else {
+ cleanedBuffer.append(ch);
+ }
+ }
+ return cleanedBuffer.toString();
+ }
+
+ /**
+ * set up to run the named project
+ *
+ * @param filename name of project file to run
+ */
+ protected void configureProject(String filename) throws BuildException {
+ configureProject(filename, Project.MSG_DEBUG);
+ }
+
+ /**
+ * set up to run the named project
+ *
+ * @param filename name of project file to run
+ */
+ protected void configureProject(String filename, int logLevel)
+ throws BuildException {
+ logBuffer = new StringBuffer();
+ fullLogBuffer = new StringBuffer();
+ project = new Project();
+ project.init();
+ project.setUserProperty( "ant.file" , new File(filename).getAbsolutePath() );
+ project.addBuildListener(new AntTestListener(logLevel));
+ ProjectHelper.configureProject(project, new File(filename));
+ }
+
+ /**
+ * execute a target we have set up
+ * @pre configureProject has been called
+ * @param targetName target to run
+ */
+ protected void executeTarget(String targetName) {
+ PrintStream sysOut = System.out;
+ PrintStream sysErr = System.err;
+ try {
+ sysOut.flush();
+ sysErr.flush();
+ outBuffer = new StringBuffer();
+ PrintStream out = new PrintStream(new AntOutputStream(outBuffer));
+ System.setOut(out);
+ errBuffer = new StringBuffer();
+ PrintStream err = new PrintStream(new AntOutputStream(errBuffer));
+ System.setErr(err);
+ logBuffer = new StringBuffer();
+ fullLogBuffer = new StringBuffer();
+ buildException = null;
+ project.executeTarget(targetName);
+ } finally {
+ System.setOut(sysOut);
+ System.setErr(sysErr);
+ }
+
+ }
+
+ /**
+ * Get the project which has been configured for a test.
+ *
+ * @return the Project instance for this test.
+ */
+ protected Project getProject() {
+ return project;
+ }
+
+ /**
+ * get the directory of the project
+ * @return the base dir of the project
+ */
+ protected File getProjectDir() {
+ return project.getBaseDir();
+ }
+
+ /**
+ * run a target, wait for a build exception
+ *
+ *@param target target to run
+ *@param cause information string to reader of report
+ *@param msg the message value of the build exception we are waiting for
+ set to null for any build exception to be valid
+ */
+ protected void expectSpecificBuildException(String target, String cause, String msg) {
+ try {
+ executeTarget(target);
+ } catch (org.apache.tools.ant.BuildException ex) {
+ buildException = ex;
+ if ((null != msg) && (!ex.getMessage().equals(msg))) {
+ fail("Should throw BuildException because '" + cause
+ + "' with message '" + msg
+ + "' (actual message '" + ex.getMessage() + "' instead)");
+ }
+ return;
+ }
+ fail("Should throw BuildException because: " + cause);
+ }
+
+ /**
+ * run a target, expect an exception string
+ * containing the substring we look for (case sensitive match)
+ *
+ *@param target target to run
+ *@param cause information string to reader of report
+ *@param contains substring of the build exception to look for
+ */
+ protected void expectBuildExceptionContaining(String target, String cause, String contains) {
+ try {
+ executeTarget(target);
+ } catch (org.apache.tools.ant.BuildException ex) {
+ buildException = ex;
+ if ((null != contains) && (ex.getMessage().indexOf(contains) == -1)) {
+ fail("Should throw BuildException because '" + cause + "' with message containing '" + contains + "' (actual message '" + ex.getMessage() + "' instead)");
+ }
+ return;
+ }
+ fail("Should throw BuildException because: " + cause);
+ }
+
+
+ /**
+ * call a target, verify property is as expected
+ *
+ * @param target build file target
+ * @param property property name
+ * @param value expected value
+ */
+
+ protected void expectPropertySet(String target, String property, String value) {
+ executeTarget(target);
+ assertPropertyEquals(property, value);
+ }
+
+ /**
+ * assert that a property equals a value; comparison is case sensitive.
+ * @param property property name
+ * @param value expected value
+ */
+ protected void assertPropertyEquals(String property, String value) {
+ String result = project.getProperty(property);
+ assertEquals("property " + property,value,result);
+ }
+
+ /**
+ * assert that a property equals &quot;true&quot;
+ * @param property property name
+ */
+ protected void assertPropertySet(String property) {
+ assertPropertyEquals(property, "true");
+ }
+
+ /**
+ * assert that a property is null
+ * @param property property name
+ */
+ protected void assertPropertyUnset(String property) {
+ assertPropertyEquals(property, null);
+ }
+
+
+ /**
+ * call a target, verify named property is "true".
+ *
+ * @param target build file target
+ * @param property property name
+ */
+ protected void expectPropertySet(String target, String property) {
+ expectPropertySet(target, property, "true");
+ }
+
+
+ /**
+ * call a target, verify property is null
+ * @param target build file target
+ * @param property property name
+ */
+ protected void expectPropertyUnset(String target, String property) {
+ expectPropertySet(target, property, null);
+ }
+
+ /**
+ * Retrieve a resource from the caller classloader to avoid
+ * assuming a vm working directory. The resource path must be
+ * relative to the package name or absolute from the root path.
+ * @param resource the resource to retrieve its url.
+ * @throws AssertionFailureException if resource is not found.
+ */
+ protected URL getResource(String resource){
+ URL url = getClass().getResource(resource);
+ assertNotNull("Could not find resource :" + resource, url);
+ return url;
+ }
+
+ /**
+ * an output stream which saves stuff to our buffer.
+ */
+ private static class AntOutputStream extends java.io.OutputStream {
+ private StringBuffer buffer;
+
+ public AntOutputStream( StringBuffer buffer ) {
+ this.buffer = buffer;
+ }
+
+ public void write(int b) {
+ buffer.append((char)b);
+ }
+ }
+
+ /**
+ * our own personal build listener
+ */
+ private class AntTestListener implements BuildListener {
+ private int logLevel;
+
+ /**
+ * Constructs a test listener which will ignore log events
+ * above the given level
+ */
+ public AntTestListener(int logLevel) {
+ this.logLevel = logLevel;
+ }
+
+ /**
+ * Fired before any targets are started.
+ */
+ public void buildStarted(BuildEvent event) {
+ }
+
+ /**
+ * Fired after the last target has finished. This event
+ * will still be thrown if an error occured during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void buildFinished(BuildEvent event) {
+ }
+
+ /**
+ * Fired when a target is started.
+ *
+ * @see BuildEvent#getTarget()
+ */
+ public void targetStarted(BuildEvent event) {
+ //System.out.println("targetStarted " + event.getTarget().getName());
+ }
+
+ /**
+ * Fired when a target has finished. This event will
+ * still be thrown if an error occured during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void targetFinished(BuildEvent event) {
+ //System.out.println("targetFinished " + event.getTarget().getName());
+ }
+
+ /**
+ * Fired when a task is started.
+ *
+ * @see BuildEvent#getTask()
+ */
+ public void taskStarted(BuildEvent event) {
+ //System.out.println("taskStarted " + event.getTask().getTaskName());
+ }
+
+ /**
+ * Fired when a task has finished. This event will still
+ * be throw if an error occured during the build.
+ *
+ * @see BuildEvent#getException()
+ */
+ public void taskFinished(BuildEvent event) {
+ //System.out.println("taskFinished " + event.getTask().getTaskName());
+ }
+
+ /**
+ * Fired whenever a message is logged.
+ *
+ * @see BuildEvent#getMessage()
+ * @see BuildEvent#getPriority()
+ */
+ public void messageLogged(BuildEvent event) {
+ if (event.getPriority() > logLevel) {
+ // ignore event
+ return;
+ }
+
+ if (event.getPriority() == Project.MSG_INFO ||
+ event.getPriority() == Project.MSG_WARN ||
+ event.getPriority() == Project.MSG_ERR) {
+ logBuffer.append(event.getMessage());
+ }
+ fullLogBuffer.append(event.getMessage());
+
+ }
+ }
+
+
+}