Compile multiple flavors of the same Java software from Ant - java

I'm looking for a way to compile a few flavors of my Java software using Ant. By flavors I mean, for instance, trial and full version.
In the code I have a
public static final boolean TRIAL
variable which specifies whether it is trial or full version. It would be very nice to be able to set it from Ant and to compile both versions automatically.
I could not find a good way to do this, while I do believe that I'm not the first one to face this problem.
In C I would simple use "ifdef" and set the define from Makefile....

Look at this: http://code.google.com/p/preprocessor/
Allows you to do stuff like this:
//#ifdef CUSTOMER1
private String abc = "abc";
//#else
private String abc = "cba";
//#endif
and set it from ant

I'd create a template file and use ANT's copy filters to change the value before compiling. I've never done it with source code, but I've used it quite a bit for configuration files.
In a source template file, you could do:
public static final boolean TRIAL = #TRIAL_VALUE#
Then in the ant build.xml, you could do this:
<filter token="TRIAL_VALUE" value="true" />
<copy tofile="${your.target.file.name.here}" filtering="true">
<fileset dir="${location.of.your.template}">
<include name="${template.file}" />
</fileset>
</copy>
I'm not sure I like the idea of doing this with a real source file (I think there's a good chance it would make the IDE angry). You might want to consider using a configuration file embedded in the jar (and use the copy filter technique on that instead)

If you have several versions of your software to avoid a easy hacking (java decompiler) I strong suggest you the use of parallel set of sources where the trial are just mocks, and so on.
With ANT you could choose the source of exactly what version will use.
Of course that this duplicate the sources, but is one possible solution without use of external software (like previous preprocessor)

Related

Change visibility on Compile

I am using Apache Ant to Build my java project into 1 big Jar File.
I would like to know if there is any way i could change visibility(from private/protected > PUBLIC) all classes, fields and methods?
So in my source code i would still have different kind of visibility, but final product(the jar, that i create by Ant) will have everything open to public.
I have checked the java obfuscators(proguard, yGuard) but they don't seem to allow such possibility.
Can this be done? Can anybody help?
If you still want to do this making public everything (and don't want to use reflection) then you can use ant replace. You just create a new directory like "temporarysrc" and copy all of you java files there, and then call this task + compile the result with javac:
<replace dir="${tmpsrc}" token="private" value="public">
<include name="**/*.java"/>
</replace>
This will be not bulletproof, because if you have some methods, variables that contains the word "private" that will mess up everything. Moreover if you have classes with multiple classes, then there will be multiple public classes, that is an error.
The advantage of this is that, if you include the created jar in a project, you can see the fields and methods from the IDE too.
Just for the record: this is only for experimenting:)

Where does HP Fortify put the intermediate files?

According to the HP Fortify documentation, the Static Code Analyzer first translates the source code into an intermediate format, and then it scans the translated code and generates a vulnerability report.
It says the translation can be done using the following Ant code:
<antcall target="compile">
<param name="build.compiler" value="com.fortify.dev.ant.SCACompiler"/>
</antcall>
This will call your "compile" target but force it to use the SCACompiler instead of the regular javac compiler.
I have run Fortify on our Java code and it produces vulnerability reports. But I do not see the intermediate files anywhere. I ran a diff between the Java class files that the regular javac compiler produced and the Java class files that the SCACompiler produced, and they were exactly the same. Are the intermediate files stored somewhere else, or does Fortify automatically delete them after performing the scan?
The intermediate files are not class or object files. They are NST (Normalized Syntax Tree) files, a proprietary format used by HP Fortify (this is discussed in the book "Secure Programming with Static Analysis". When translating with a build ID, such as:
sourceanalyzer -b test ant
Then it will be stored in the project working directory. In Windows, typically:
%USERPROFILE%\AppData\Local\Fortify\sca<version>\build\test
or on other platforms:
~/.fortify/sca<version>/build/test
this will then contain the canonicalized path to the NST, as was performed during the translation. These can then be used to scan multiple times if needed, but should be "cleaned" if scanning a separate new (or updated) codebase.
For ant integration I think it depends on which version of Ant, and the way you are translating, but this way I think it just calls the sourceanalyzer.jar file (which contains the com.fortify.dev.ant.SCACompiler class) in order to hook into the JVM and follow the build to create the NST files needed for scanning. I don't believe it's actually a separate version of javac, although perhaps there is a separate version under <SCA installation directory>/jre/ which it may use.
Lavamunky is correct about the default path for the working directory. You can change this in the following locations:
1. FortifyInstallRoot\Core\config\fortify.properties: com.fortify.WorkingDirectory
2. FortifyInstallRoot\Core\config\fortify-sca.properties: com.fortify.sca.ProjectRoot
Note that you need to use / as the path delimiter instead of \ inside of the config files. Inside of the folder specified by those paths, the pattern is: sca\build\.
You can also specify these at runtime:
sourceanalyzer -b MyBuild -Dcom.fortify.WorkingDirectory=C:\Fortify\Work -Dcom.fortify.sca.ProjectRoot=C:\Fortify\Work
The path to the working files would then be:
C:\Fortify\Work\sca<version>\build\MyBuild\

How to run all rulesets from a folder using PMD Ant in Eclipse?

I am trying to run PMD from Ant in Eclipse when I build the project.
This is my build.xml file:
<taskdef name="pmd" classname="net.sourceforge.pmd.ant.PMDTask"/>
<target name="check_pmd">
<pmd rulesetfiles="C:\Users\Nikolay\ProjectName\lib\rulesets\java\basic.xml">
<formatter type="html" toFile="pmd_report.html" toConsole="true"/>
<fileset dir="C:\Users\Nikolay\ProjectName\src">
<include name="**/*.java"/>
</fileset>
</pmd>
</target>
It works well for basic.xml, but I want to run for all rulesets in java folder (It has around 20 rulesets) So I have tried:
<pmd rulesetfiles="C:\Users\Nikolay\ProjectName\lib\rulesets\java\*.xml">
<pmd rulesetfiles="C:\Users\Nikolay\ProjectName\lib\rulesets\java\*">
But both of them fail when I try to run. Is there a way to specify folder, not a single file without specifying list of files manually?
For future readers to configure Ant PMD under Eclipse:
Download pmd-bin.zip from official website
Unpack pmd.jar, jaxen.jar and asm.jar
Add jars above to Window - Preferences - Ant - Runtime - Ant Home Entries - Add External JARs
Unpack rulesets folder
Reference location of ruleset from <pmd rulesetfiles=...>
(expanding answer from coolfan for ant task)
The documentation of PMD rulesetfiles says it is comma separated list of files.
rulesetfiles A comma delimited list of ruleset files
('rulesets/basic.xml,rulesets/design.xml'). If you write your own
ruleset files, you can put them on the classpath and plug them in
here. Yes, unless the ruleset nested element is used
Ant provides a way to convert fileset into such a format. The task is pathconvert
here is an example from website
<fileset dir="${src.dir}" id="src.files">
<include name="**/*.java"/>
</fileset>
<pathconvert pathsep="," property="javafiles" refid="src.files"/>
Maybe the param doesn't support wildcard, as the document suggests.
A quick look over its source code also supports my guess, see RuleSetReferenceId.java, line 194.
So, it takes a property which contains a "list" using , as delimiter, like:
"rule1,rule2,rule3,path-to-rule-file4"
The workaround could be scanning the directory, list all the rule-xml files, and build a property in the comma-delimited format and then pass it to <pmd> task.
Unfortunately, I don't know any ant task which can do this. So you may have to write some code.
I can come up with two ways:
write a ant task; there are many Q&As about this for Java, like this.
write groovy inside a <groovy> task; also many Q&As.
EDIT:
Jayan suggests <pathconvert> task, which should be the right answer.
In the pmd library jar there is an all-java.xml where all the rule sets have been included.
Try to use the following:
<pmd rulesetfiles="rulesets/internal/all-java.xml">

creating javadoc with ant for only the dependent classes of a given class (java file)

I want to create javadoc with ant from a java source file and just from the dependent classes of this file. These are in a java project, but i don't need javadoc from all the java files.
Is there a way to create javadoc like javac
javac includes="package/Java_source.java" destdir="dir/classes"
that compiles the source files and just the dependent classes? If there isn't, then is there another way?
Thanks, Tamas
Well you can add a fileset and / or a packageset parameter:
Example with a fileset:
<javadoc
destdir="docs/api"
author="true"
version="true"
use="true"
windowtitle="Test API">
<fileset dir="src">
<include name="foo/bar/BaseClass.java"/>
<include name="foo/bar/baz/DependentClassA.java"/>
<include name="foo/bar/phleem/DependentClassB.java"/>
</filset>
</javadoc>
But you will have to figure out the dependent classes yourself, I'm afraid.
Reference:
Ant javadoc Task
There is no way to find out what the "dependent classes" are without starting the job. The only thing I can think of is a brutal hack:
On the compiled classes, use a byte code analysis tool like ASM and check all classes in the code base for their usage of your given class (source code analyis is not enough because of possible wildcard imports and same-package usage). From the List of used classes, build a list of source files, and pass that to the Javadoc task (probably best to create an Ant task that does all this). But this is heavy stuff.

Does Ant Support File-based Dependencies?

I would like to make an ant dependency where the target file depends on a source file. How do you describe this in ant?
For example, convert this Make target to ant
data.txt: header1.txt body.txt footer.txt
cat header1.txt body.txt footer.txt > data.txt
You might be able to do something like this, but it's starting to sound like scripting. Ant isn't a scripting language. If you have a lot of "if/then/else" logic in mind you're probably doing it wrong.
Please describe "other data". Are we talking about copying files? Is this a devl/test/prod environment issue? In that case, you can certainly pass in a parameter specifying environment name and using conditional tests to decide which set to copy. Read this to see how.
If you're just wanting to bring files in one directory up-to-date with respect to your source tree,
you might use the sync task. Here's a basic example from the docs:
<sync todir="site">
<fileset dir="generated-site"/>
</sync>
overwrites all files in site with
newer files from generated-site,
deletes files from site that are not
present in generated-site.
If you need to determine which resources need update,
in order to carry out a more complex operation than a sync,
you might use the ant-contrib outofdate task. For example
<outofdate property="compile.needed" outputsourcespath="sources.for.recompile">
<sourcefiles>
<fileset dir="${src}" includes="*.c"/>
</sourcefiles>
<mapper type="glob" dir="${src}" from="*.c" to="${obj}/*.o"/>
</outofdate>
will set compile.needed to true if any object files are out-of-date compared to source,
and also set the path sources.for.recompile with a list of just the sources that need recompile -
you can then compile for just those sources.
(The assumption here is that a single file in the build output area is directly related to one source.)
My simple solution right now is to manually add a test for the source/dest file age in my shell script called from exec task in ant.

Categories

Resources