Monday Jul 28, 2008

Groovy Generation of NetBeans Modules

I'm continuing to be impressed with the usefulness of Groovy in getting started with source structures for applications. Yesterday I showed how to generate a NetBeans Platform application from a Groovy script. Today I present... a Groovy script that will generate a NetBeans module. This is pretty much the absolutely barest NetBeans module imaginable. Nonetheless, a NetBeans module is what it is, and no different from the one you get via the "New Module" wizard in the "New Project" dialog. And once you've run this script, you'll be able to open the module in the IDE and begin adding features to it right away.
package generators

def id = new Date().time
def folder = System.getProperty("user.home") + "/NewModule" + id;
def name = "NewModule" + id;
def pkgs = "org/netbeans/modules/demo"

println "Generating project ${name} in folder ${folder}";

def manifest_mf = """\\
Manifest-Version: 1.0
OpenIDE-Module: ${name}
OpenIDE-Module-Layer: ${pkgs}/layer.xml
OpenIDE-Module-Localizing-Bundle: ${pkgs}/Bundle.properties
OpenIDE-Module-Specification-Version: 1.0

"""

def build_xml = """\\
<?xml version="1.0" encoding="UTF-8"?>
<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
<!-- for some information on what you could do (e.g. targets to override). -->
<!-- If you delete this file and reopen the project it will be recreated. -->
<project name="${name}" basedir=".">
    <description>Builds, tests, and runs the project ${name}.</description>
    <import file="nbproject/build-impl.xml"/>
</project>

"""

def layer_xml = """\\
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
</filesystem>

"""

def bundle_properties = """\\
OpenIDE-Module-Name=${name}

"""

def build_impl_xml = """\\
<?xml version="1.0" encoding="UTF-8"?>
<!--
\*\*\* GENERATED FROM project.xml - DO NOT EDIT  \*\*\*
\*\*\*         EDIT ../build.xml INSTEAD         \*\*\*
-->
<project name="${name}-impl" basedir="..">
    <property file="nbproject/private/platform-private.properties"/>
    <property file="nbproject/platform.properties"/>
    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
        <attribute name="name"/>
        <attribute name="value"/>
        <sequential>
            <property name="@{name}" value="\\${@{value}}"/>
        </sequential>
    </macrodef>
    <property file="\\${user.properties.file}"/>
    <nbmproject2:property name="harness.dir" value="nbplatform.\\${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
    <nbmproject2:property name="netbeans.dest.dir" value="nbplatform.\\${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
    <fail message="You must define 'nbplatform.\\${nbplatform.active}.harness.dir'">
        <condition>
            <not>
                <available file="\\${harness.dir}" type="dir"/>
            </not>
        </condition>
    </fail>
    <import file="\\${harness.dir}/build.xml"/>
</project>

"""
def platform_properties = """\\
nbplatform.active=default

"""
def project_properties = """\\
javac.source=1.5
javac.compilerargs=-Xlint -Xlint:-serial

"""
def project_xml = """\\
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://www.netbeans.org/ns/project/1">
    <type>org.netbeans.modules.apisupport.project</type>
    <configuration>
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
            <code-name-base>${name}</code-name-base>
            <standalone/>
            <module-dependencies/>
            <public-packages/>
        </data>
    </configuration>
</project>

"""
def base = new File(folder);
base.mkdirs();
def src = new File(folder + File.separator + "src" + File.separator + "${pkgs}");
src.mkdirs();
def nbproject = new File(folder + File.separator + "nbproject");
nbproject.mkdirs();
new File(folder + File.separator  +"build.xml").write(build_xml);
new File(folder + File.separator  +"manifest.mf").write(manifest_mf);
new File("${src}" + File.separator + "layer.xml").write(layer_xml);
new File("${src}" + File.separator + "Bundle.properties").write(bundle_properties);
new File("${nbproject}" + File.separator + "build-impl.xml").write(build_impl_xml);
new File("${nbproject}" + File.separator + "platform.properties").write(platform_properties);
new File("${nbproject}" + File.separator + "project.properties").write(project_properties);
new File("${nbproject}" + File.separator + "project.xml").write(project_xml);

println("Done.")

The screenshot below has two nodes highlighted. The first is the node of the Groovy script that I ran to generate the whole of the source structure represented by the second highlighted node:

I.e., running the above script gives you a compilable starting point for creating NetBeans modules, without needing to go through any wizards to do so. The script runs in the space of a split second, generating everything I need. Plus, it's very simple to tweak the script to make it generate something different. Imagine, for example, how easy it would be to have a few predefined actions or windows in your module? Just go through the motions using the IDE's tools and then copy the generated code into the script above and then you'll never need to create them again via wizards, but always via your script instead.

About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« July 2008 »
SunMonTueWedThuFriSat
  
4
5
6
11
12
13
14
17
26
30
  
       
Today