Saturday, 27 March 2010

License Project in NetBeans

I resurrected an old project last week, with the intention of sharing some of the code. Specifically I wanted to add a GPL license to the project but it's not uncommon to want to add some sort of standard header to source code files. Achieving that with NetBeans 6.8 threw up some interesting aspects of NetBeans itself, its interaction with Maven and a nice trick with Bash scripting ...

Licenses in NetBeans

I think Templates in NetBeans are fairly well known and commonly modified. Perhaps less well known is the default inclusion of a license statement which can be configured on a project by project basis.

If you go to Tools -> Templates and open the template for a Java class file, you'll find this little section at the top:

<#assign licenseFirst = "/*">
<#assign licensePrefix = " * ">
<#assign licenseLast = " */">
<#include "../Licenses/license-${project.license}.txt">

Out of the box, the project.license variable is set to a default license, which produces this, which you will have no doubt seen if you use NetBeans:

/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

If you are using a standard NetBeans project, by editing the nbproject/project.properties file in your NetBeans project directory, you can modify the license applied to each new file. (In the rest of this post, where I'm using shell commands, I'm going to assume you are working in your project directory).

Edit nbproject/project.properties with your favourite text editor, or a quick way if you are using a Unix is:

$ echo "project.license=gpl30" >> nbproject/project.properties

The variable is set to gpl30 in this case for GPL 3.0. The other licenses are listed under Tools -> Templates -> Licenses. Note that NetBeans automatically prefixes "license-" and appends ".txt", so just specify the middle part.

Now when you create new source files, NetBeans will, where appropriate, add the license comment that you specified.

If you aren't quite happy with the format, you can edit the license template itself. This can be used in conjunction with the User.properties template in Tools -> Templates -> User Configuration Properties.

User.properties
user=Your Full Name
email=yourEmail@yourDomain
company=Your Company
license-gpl30
<#if licenseFirst??>
${licenseFirst}

${licensePrefix} Copyright (c) ${company} ${date?date?string("yyyy")}
${licensePrefix}
${licensePrefix} This program is free software: you can redistribute it and/or modify
...
${licensePrefix} Please refer any queries to ${user} <${email}>

But what if you are using Maven? (If not, why not?) In this case, there is no nbproject/project.properties file. The solution is actually quite simple. Edit your POM and add a new properties section, or extend an existing one, with this hint:

pom.xml
...
<properties>
    <netbeans.hint.license>gpl30</netbeans.hint.license>
</properties>
...

Obviously it would be nice if you could configure these licenses into your project using NetBeans project properties, but for now, you have to edit nbproject/project.properties or pom.xml.

Adding License Header to Existing Code using Bash

N.B. I'm using Ubuntu, other Unix variants that don't use Bash or Bourne shell deriviatives will be slightly different.

My first thought was to use a combination of find and cat to prepend the license, stored in a text file, to all the Java files in my project. Something like this:

$ find . -name '*.java' -exec cat $HOME/Documents/gpl.txt {} > {} \;

But it doesn't work. Aside from the possibility that such a command would clobber the input file before it was even read, I could find neither documentation nor examples of using shell redirection within the -exec.

So I took the easy way out and made a simple Bash script to prepend the GPL license to a list of files on the command line. Default on Ubuntu is to add $HOME/bin to your path. Don't forget to:

$ chmod +x $HOME/bin/prepend_gpl

$HOME/bin/prepend_gpl
#!/bin/bash

# Use Ubuntu's auto-mounted RAM disk for temporary files
TMP=/dev/shm

# Use GPL environment variable if set, otherwise use default
if [ ! $GPL ]; then
    GPL=$HOME/Documents/gpl.txt
fi

# Check the license file exists
if [ ! -e $GPL ]; then
    echo $GPL not found
    exit -1
fi

# Prepend the license to each file listed on the command line
while [ $1 ]; do
    cat $GPL $1 > $TMP/prepend_gpl.tmp 
    mv $TMP/prepend_gpl.tmp $1 
    shift
done

Nothing too tricky there, making use of a temporary file to hold the composited file and renaming back to overwrite the original. Note the /dev/shm mount point on Ubuntu, which is an auto-mounted RAM disk in shared memory, ideal for temporary files.

$ prepend_gpl *.java

That deals with all .java files in a directory. To apply to a whole project, it can be used with find from the root of the project:

$ find . -name '*.java' -exec prepend_gpl {} \;

Job done, but I was still curious if I could do it in a one-liner and found this neat trick of redirecting a command into a Bash loop structure. This uses a while loop, but other constructs work in a similar way.

$ while read f; do cat $HOME/Documents/gpl.txt "$f" > /dev/shm/addgpl.tmp && mv /dev/shm/addgpl.tmp "$f"; done < <(find . -name '*.java')

Does it count as a one-liner? Will I be able to recall the syntax off the top of my head? I'll leave you to decide!

3 comments:

Vaulter said...

Works for me! Great
Thanks

Kenny said...

Thanks, for sharing your method for licensing your NetBeans project. A really useful guide.

I already had all the program written, and found it very tedious to manually edit every .java file, so you're little Bash-Script turned out to be a very useful one.

Anonymous said...

Excellent, especially the POM and user.properties part. Now it all works. Thanks!

Followers