IntelliJ IDEA - can I have automatically incremented build (version) number? - java

Can I set somehow IntelliJ building process to pre-process Java source codes and give me ever incrementing build number? Something like:
int myBuildNumber = INTELLI_J_IDEA_MAGIC_WHICH_WILL_INCREMENT_EVERY_BUILD;

Ok so with hint from AtomHeartFather I got it.
First we need to write an ant xml file. This file will create file where build number will be stored and incremented and then it will look through your source code file ${src}/com/yourPath/Main.java
for variable public static final String BUILD_NUMBER = ".*"; and replace it with current build number
The xml file would look like this:
<project name="MyProject" default="init" basedir=".">
<description>
simple example increment build variable
</description>
<!-- set global properties for this build -->
<property name="src" location="../src"/>
<target name="init">
<echo file="myAntOut.txt">My first ant ${src} ${line.separator}</echo>
<buildnumber/>
<replaceregexp file="${src}/com/yourPath/Main.java"
match="public\s+static\s+final\s+String\s+BUILD_NUMBER\s+=\s+".*";"
replace="public static final String BUILD_NUMBER = "${build.number}";"
byline="true"
/>
</target>
</project>
Then in your intelliJ (I'm using 14.0.3) you click on View->Tool Windows->Ant Build. Then + and browse to your xml file (note that current path used by your xml will be the path to that xml file itself - not inteliJ project - thus you may want to correct the part location="../src" depending on where you store your xml). Than you shall see our target init you can select it and click play button. If it works you shall see BUILD_NUMBER incremented in you source code file Main.java. Now the important trick how to make it automatically: Just right click on init and select Execute on->Before Compilation. Done :)

Related

How to extract properties from Ant file (build.xml) into Java code

Once the build.xml file is executed, I want to check some properties in the build.xml to handle some errors in my Java code.
For infos, my Ant file (build.xml) is executed this way (not all the code is present):
ILaunchConfigurationWorkingCopy workingCopy = type.newInstance(null,
ITaskLauncherConstants.LAUNCHER_NAME);
/* Configure the ILaunchConfiguration (not all setAttribute calls are presents) :*/
workingCopy.setAttribute(IExternalToolConstants.ATTR_LOCATION, "build.xml");
/* Launch the task, where monitor is a IProgressMonitor */
ILaunch lc = workingCopy.launch(ILaunchManager.RUN_MODE, monitor);
And in my build.xml file I have some properties :
<!-- In Ant File -->
<property name="fail.message" value="true" />
Is it possible to check the content of the property in Java code ? Something like :
/* In Java code */
lc.getProperty("fail.message");
Of course, this would mean that the class would "record" the build.xml properties.
Same question has been asked 6 months ago, but the answer is not working (I tried):
How to set a property in java code using build.xml
Thanks for any suggestion.
A simple approach would be using echoproperties task in your ant buildscript, means writing all or desired (via echoproperties attribute prefix) properties to a file and load that file in java afterwards.
From ant manual echoproperties, attribute destfile :
If specified, the value indicates the name of the file to send the
output of the statement to. The generated output file is compatible
for loading by any Java application as a property file. If not
specified, then the output will go to the Apache Ant log.
<echoproperties prefix="fail" destfile="what/ever/foo.properties"/>

custom ant task with additional libraries

i was writing a custom task for ant in java and my idea was that i can give someone the .jar which contains the java files like the classes and the libraries and the build.xml for ant and he can use it.
If i export my java project the .jar (antTask.jar) contains :
a folder for the compiled classes, one for the libraries, meta-inf folder and .classpath .project files
The ant build.xml looks like this:
<?xml version="1.0" ?>
<project name="repair" basedir="." default="repairTask">
<taskdef name="antTask" classpath="antTask.jar" classname="def.RepairTask"/>
<target....
i don't really understand all this classpath stuff, so can someone tell me what i have to add in my build file so it will work only with this .jar file without the java code sources?
right now i am getting an error that ant can't find one of the libraries i use in the java code with this error (but the antTask.jar contains this lib as another .jar):
taskdef A class needed by class def.RepairTask cannot be found: org/apache/commons/...
using the classloader AntClassLoader[C:...\AntTask\antTask.jar]
i am trying for hours but i just can't figure out how i have to edit my build.xml so i just have to point to this single .jar file and it works..
Thank you guys
All a taskdef does is associate a task name to a classfile that contains the code to execute that task. However, in order to find that classfile, you need to tell <taskdef/> where to find the jar that contains it. That's all classpath does is.
You don't have to define a classpath with the <taskdef/> task. Ant by default looks for all jars that contain code for the <taskdef/> tasks in $ANT_HOME/lib. If you copy your jar to that folder, you could simply define that task this way:
<taskdef name="antTask" classname="def.RepairTask"/>
No need for the classpath. However, I actually don't recommend doing that. Instead, I recommend putting that jar file into your project, so other developers can use your project without having to install that task jar into their $ANT_HOME/lib folder:
<taskdef name='antTask' classname="def.RepairTask">
<classpath>
<fileset dir="${basedir}/antlib/antjar"/>
</classpath>
</taskdef>
Now, when a developer checks out the project that requires the optional task jar, that task jar comes with the project, so they can simply do their build.
There are two ways to define tasks. One is to give a task a name, and then tell <taskdef/> what classfile is associated with that jar as you did above. However, you can also define a resource that also will associate task names with their classes. Here's a common way to include the Ant-Contrib ant tasks:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<fileset dir="${basedir}/antlib/antcontrib"/>
</classpath>
</taskdef>
If I expand the antcontrib jar, I'll see it contains a net/sf/antcontrib/antcontrib.properties1 file inside the jar. That file looks something like this:
...
# 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
relentless=net.sf.antcontrib.logic.Relentless
# Math Tasks
math=net.sf.antcontrib.math.MathTask
...
All it does is define each task with a classfile for that task. I would recommend you do something similar with your custom ant task. This way, if you decide to include other tasks, you can simply modify this one file, and developers won't have to change their <taskdef/> definition in their jars, or add in multiple ones.
By the way, you should make good and sure that your class doesn't clash with another class that someone else may use. You might want to give your classname a full path that includes a unique prefix:
<taskdef name='antTask' classname="com.vegicorp.anttasks.RepairTask">
Assuming you work for VegiCorp...
1 Ant contrib tasks contain two such files. One is XML format and the other is in properties format. I always use the XML format, and that's what your suppose to use when you define Ant Task resources. I used the properties file because it's a simpler format and easier to see what's going on.

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">

Android - use ant to create build configurations that change configuration values

What I want is a way to have settings that are dependent on build configuration. To give a specific example, my android application connects to a web service. In development, I want the service url to be pulled in from a configurable value. In Test, I want a different value pulled in. In production, yet another value.
So, in code I have something like this:
public class HttpRequestHelper
{
private static String GetServiceUrl(ServiceAction action)
{
return serviceUrl + action.toString();
}
}
By default (when debugging/running through eclipse), I want that url to be http://localhost:1234
In Test I want https://test.mydomain.com
In Production I want https://mydomain.com
I am new to eclipse and ant and it has been a long time since I used java. How do I go about setting this up? What should the build.xml look like? I understand that when I want to build the test/prod versions I will need to use the command line. That's okay. But I don't know how to get this serviceUrl auto-set dependent on the build. I'm not even sure the best place to put this information (a resource, a properties file?). I really want to avoid setting it, building, setting it, building, etc.
As answers mentioned above says, you have to place the URLs in a property file like dev.properties, test.properties, prod.properties etc..
Now only thing that you need to do is making your build intelligent enough to choose a property file depending upon environment.
That can be done by passing a parameter to ANT, something like:
$ ant -file MyBuild.xml -DcurrentEnv=dev (For Development environment)
$ ant -file MyBuild.xml -DcurrentEnv=test (For Test)
$ ant -file MyBuild.xml -DcurrentEnv=prod (For Production)
Inside your build script, this is how you can include your property file:
<target name="jarMe">
<jar destfile="sample.jar" basedir="src" includes="${currentEnv}.properties"/>
</target>
With this in place, whatever name you supply at the time of build, property file with that name will be picked up.
You could try to have a following property file in your build.properties file:
service.url=*
And you could have http://localhost:1234 or https://test.mydomain.com in local.properties for your development and integration testing, and it could be set to https://mydomain.com in default.properties.
By do ing this, you have will get different value for service.url in different build environment. You could use that value to generate a config file, and parse it into your code, or set it to env variable, or just put it into a resource file, and Android will read it for you:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="service-url">##toben_to_be_replaced_during_build_time##</string>
</resources>
I would start by placing the urls into a properties file that you can then place onto the classpath. Make a test and a production properties file. Then depending on the build place the correct file onto the classpath and pull the properties at runtime.
Found a tutorial which goes through all the details of using ant to automate a build system, to create and use build configurations, as well as to build the release project with one command. Here it is: http://www.androidengineer.com/2010/06/using-ant-to-automate-building-android.html
Seems a little long, but it goes through all the steps and details involved.

Ant: fileset "dir" attribute with a runtime expanded full path

Let's say I have a file-system that looks a little something like this:
C:\stuff\build.xml
C:\stuff\myfolder\library1.jar
C:\stuff\myfolder\library2.jar
Inside build.xml, I want to define a path that looks like this:
<path id="some.id">
<fileset dir="myfolder">
<include name="**/*.jar"/>
</fileset>
</path>
Normally that works fine. However, I am calling my own custom Ant Task that will inherit any references (including the path "some.id") and that custom Ant Task will call a build.xml that lives in a different basedir. Therefore, the "dir" attribute in the fileset is no longer valid.
Is there a way to define a "dir" such that it remains valid no matter where the second build.xml lives?
I essentially want to do something like this:
<fileset dir="${expand.current.directory}/myfolder">
So when I call the second build.xml it will understand that the "dir" attribute is the location of:
<fileset dir="c:\stuff\myfolder">
Edit: Furthermore, I want a solution that allows me to copy the "stuff" project from one machine to another without requiring a change to the build. For example, if the "stuff" project is on the C: drive and I copy the project over to a D: drive on another machine, I want the build to continue to work without me having to go into the build and change the letter C to the letter D.
I think you're after the ${user.dir} property - which is the current working directory.
All java System.properties are available as ant properties.
Option 1:
You can define an Ant property.
At the beggining of the file you can define this property:
<property name="myproject.root.path" location="C:/stuff/"/>
And then, use it:
<fileset dir="${myproject.root.path}/myfolder">
Option 2:
You can also define it at an external build.properties file, located at the same folder in wich the build.xml file is.
File C:\stuff\build.properties
myproject.root.path=C:/stuff/
And, to make use of this file you have to add this line at the Ant XML file (recommended before the tasks definition):
<property file="build.properties"/>
Once you have this file included, you can use the properties along the project, the same way as seen at option 1:
<fileset dir="${myproject.root.path}/myfolder">
You can add more than one properties file.
Note that paths are defined using slashes, and not back-slashes.

Categories

Resources