blob: 75d8e144b846b9150a4d535e4d9bdc195df59b46 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- -*- xhtml -*- -->
<title>NetBeans Project Type Extension Module Tutorial for NetBeans Platform 6.9</title>
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css"/>
<meta name="AUDIENCE" content="NBUSER"/>
<meta name="TYPE" content="ARTICLE"/>
<meta name="EXPIRES" content="N"/>
<meta name="developer" content="gwielenga@netbeans.org"/>
<meta name="indexed" content="y"/>
<meta name="description"
content="A short guide to using the APIs for extending project types."/>
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -->
<!-- Use is subject to license terms.-->
</head>
<body>
<h1>NetBeans Project Type Extension Module Tutorial</h1>
<p>This tutorial demonstrates how to extend an existing project type.</p>
<p><strong class="notes">Note: </strong>This document uses the NetBeans IDE 6.9 Release or above. If you
are using an earlier version, see <a href="60/nbm-projectextension.html">the 6.0/6.1 version
of this document</a>.</p>
<p><b>Contents</b></p>
<p><img src="../../images/articles/69/netbeans-stamp-69-70.png" class="stamp" width="114" height="114" alt="Content on this page applies to NetBeans IDE 6.9" title="Content on this page applies to NetBeans IDE 6.9"/></p>
<ul class="toc">
<li><a href="#intro">Introduction to Project Extensions</a></li>
<li><a href="#creatingthemoduleproject">Creating the Module Project</a></li>
<li><a href="#settingdependencies">Setting Dependencies</a></li>
<li><a href="#extendingthelookup">Extending the Lookup</a></li>
<li><a href="#extendingthelogicalview">Extending the Logical View</a></li>
<li><a href="#extendingthecustomizer">Extending the Project Customizer</a></li>
<li><a href="#building">Installing the Module</a></li>
</ul>
<p><b>To follow this tutorial, you need the software and resources listed in the following
table.</b></p>
<table>
<tbody>
<tr>
<th class="tblheader" scope="col">Software or Resource</th>
<th class="tblheader" scope="col">Version Required</th>
</tr>
<tr>
<td class="tbltd1"><a href="https://netbeans.org/downloads/index.html">NetBeans IDE</a></td>
<td class="tbltd1">version 6.9 or above</td>
</tr>
<tr>
<td class="tbltd1"><a href="http://java.sun.com/javase/downloads/index.jsp">Java Developer Kit (JDK)</a></td>
<td class="tbltd1">Version 6</td>
</tr>
</tbody>
</table>
<p>You will also make use of this icon, which you
can right-click here and download: <img alt="" src="../../images/tutorials/projectextensions/webPagesBadge.gif" /></p>
<p class="tips">Optionally, for troubleshooting purposes, you can <a href="http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=14034">download the
completed sample</a> and inspect the sources.</p>
<h2 class="tutorial"><a name="intro"></a>Introduction to Project Extensions</h2>
<p>New NetBeans IDE APIs since NetBeans IDE 6.0
enable you to add new nodes to an existing project type's logical view, new objects to an
existing project type's lookup, and new panels to an existing project type's Project
Properties dialog box. For example, in this tutorial,
to illustrate these extensions, we extend the web application
project type, by adding a new 'Important Files' node, exposing the content of the
project's 'nbproject' folder, as shown here:</p>
<p><img src="../../images/tutorials/projectextensions/result-69.png" alt="New node"/></p>
<p>Prior to NetBeans IDE 6.0, no NetBeans IDE APIs existed for extending existing project types.
Instead, you would need to create new project types from scratch. From 6.0 onwards, you are
recommended to extend existing project types rather than create new ones. This will
keep the number of project types to a minimum and avoid a large number of project
types with very small differences. However, it is still possible to create project
types from scratch, as before.</p>
<p>Annotations are used throughout this tutorial to register the lookup extension,
logical view extension, and project customizer extension. As you will see
below, the extensions will be registered for the project type
"org-netbeans-modules-web-project", which is the web application project type.
Here is a list of strings representing other project types supported by
NetBeans IDE:</p>
<ul>
<li>org-netbeans-modules-ant-freeform</li>
<li>org-netbeans-modules-apisupport-project</li>
<li>org-netbeans-modules-apisupport-project-suite</li>
<li>org-netbeans-modules-j2ee-archiveproject</li>
<li>org-netbeans-modules-j2ee-clientproject</li>
<li>org-netbeans-modules-j2ee-earproject</li>
<li>org-netbeans-modules-j2ee-ejbjarproject</li>
<li>org-netbeans-modules-java-j2seproject</li>
</ul>
<p>Other project types may be available, depending on the modules that are part
of your specific installation of NetBeans IDE or other application on the
NetBeans Platform.</p>
<h2 class="tutorial"><a name="creatingthemoduleproject"></a>Creating the Module Project</h2>
<p>We begin by working through the New Module Project
wizard. At the end of it, we will have a basic
source structure, with some default files, that
every NetBeans module requires.</p>
<ol>
<li>Choose File &gt; New Project (Ctrl+Shift+N). Under Categories, select NetBeans Modules.
Under Projects, select Module. Click Next.</li>
<li>In the Name and Location panel, type <tt>ImportantWebFiles</tt> in the Project Name field.
Change the Project Location to any directory on your computer. Leave the Standalone Module option
and Set as Main Project checkbox selected. Click Next.</li>
<li>In the Basic Module Configuration panel, type <tt>org.netbeans.modules.importantwebfiles</tt>
in Code Name Base.</li>
<li>Select "Generate XML Layer". Leave the
locations of both the localizing bundle and the XML layer file
so that they will be stored in a package with
the name <tt>org/netbeans/modules/importantwebfiles</tt>. Click Finish.</li>
</ol>
<p> The IDE creates the <tt>ImportantWebFiles</tt>
project. The project contains all of your sources and
project metadata, such as the project's Ant build script. The project
opens in the IDE. You can view its logical structure in the Projects window (Ctrl-1) and its
file structure in the Files window (Ctrl-2).</p>
<!-- ===================================================================================== -->
<h2><a name="settingdependencies"></a>Setting Dependencies</h2>
<p>We will need to make use of several NetBeans APIs. In this
step, we select the modules that provide the NetBeans APIs
that we will need.</p>
<ol>
<li>Right-click the project node and
choose Properties. The Project Properties dialog box opens.</li>
<li>In the Libraries panel, add dependencies on the
following modules:
<ul>
<li>Datasystems API</li>
<li>File System API</li>
<li>Nodes API</li>
<li>Project API</li>
<li>Project UI API</li>
<li>Utilities API</li>
<li>Web APIs</li>
</ul>
<p>The Libraries panel should now look as follows:</p>
<p><img src="../../images/tutorials/projectextensions/add-deps-69.png" alt="Select Project panel."/></p>
</li>
<li>Click OK.</li>
</ol>
<!-- ===================================================================================== -->
<h2><a name="extendingthelookup"></a>Extending the Lookup</h2>
<p>We start by implementing the <tt>LookupProviderImpl</tt>
class, which we will register via an annotation.</p>
<ol>
<li><p>Create a Java class called <tt>LookupProviderImpl</tt>.</p></li>
<li><p>Change the default code to the following:</p>
<pre class="examplecode">@LookupProvider.Registration(projectType = "org-netbeans-modules-web-project")
public class LookupProviderImpl implements LookupProvider {
public Lookup createAdditionalLookup(Lookup lookup) {
Project prj = lookup.lookup(Project.class);
<b>//If there is a web module provider in the
//project's lookup, add a new lookup item to
//the lookup, which we will look for to determine
//whether a node should be created:</b>
WebModuleProvider wmp = lookup.lookup(WebModuleProvider.class);
if (wmp != null) {
return Lookups.fixed(new MyCoolLookupItem(prj));
}
<b>//If there is no web module in the lookup,
//we do not add a new item to our lookup,
//so that later a node will not be created:</b>
return Lookups.fixed();
}
}</pre> </li>
<li>Create a new Java class called <tt>MyCoolLookupItem</tt>.</li>
<li><p>Change the default code to the following:</p>
<pre class="examplecode">public class MyCoolLookupItem {
public MyCoolLookupItem(Project prj) {
}
}</pre> </li>
</ol>
<!-- ===================================================================================== -->
<h2><a name="extendingthelogicalview"></a>Extending the Logical View</h2>
<p>We start by implementing the <tt>ImportantFilesNodeFactoryImpl</tt>
class, which we will register via an annotation.</p>
<ol>
<li><p>Create a Java class called <tt>ImportantFilesNodeFactoryImpl</tt>.</p></li>
<li><p>Change the default code to the following:</p>
<pre class="examplecode">@NodeFactory.Registration(projectType = "org-netbeans-modules-web-project")
public class ImportantFilesNodeFactoryImpl implements <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-projectuiapi/org/netbeans/spi/project/ui/support/NodeFactory.html">NodeFactory</a> {
Project proj;
public <a href="https://netbeans.org/download/dev/javadoc/org-netbeans-modules-projectuiapi/org/netbeans/spi/project/ui/support/NodeList.html">NodeList</a> createNodes(Project project) {
this.proj = project;
<b>//If there is no 'nbproject' folder,
//return an empty list of nodes:</b>
if (proj.getProjectDirectory().getFileObject("nbproject") == null) {
return NodeFactorySupport.fixedNodeList();
}
<b>//If our item is in the project's lookup,
//return a new node in the node list:</b>
MyCoolLookupItem item = project.getLookup().lookup(MyCoolLookupItem.class);
if (item != null) {
try {
ImportantFilesNode nd = new ImportantFilesNode(proj);
return NodeFactorySupport.fixedNodeList(nd);
} catch (DataObjectNotFoundException ex) {
Exceptions.printStackTrace(ex);
}
}
<b>//If our item isn't in the lookup,
//then return an empty list of nodes:</b>
return NodeFactorySupport.fixedNodeList();
}
}</pre></li>
<li>Create a new Java class called <tt>ImportantFilesNode</tt>.</li>
<li><p>Change the default code to the following:</p>
<pre class="examplecode">public class ImportantFilesNode extends <a href="https://netbeans.org/download/dev/javadoc/org-openide-nodes/org/openide/nodes/FilterNode.html">FilterNode</a> {
private static Image smallImage =
ImageUtilities.loadImage("/org/netbeans/modules/importantwebfiles/webPagesBadge.gif"); // NOI18N
public ImportantFilesNode(Project proj) throws DataObjectNotFoundException {
super(DataObject.find(proj.getProjectDirectory().getFileObject("nbproject")).getNodeDelegate());
}
public String getDisplayName() {
return "Important Files";
}
<b>//Next, we add icons, for the default state, which is
//closed, and the opened state; we will make them the same.
//Icons in project logical views are
//based on combinations--you must combine the node's own icon
//with a distinguishing badge that is merged with it. Here we
//first obtain the icon from a data folder, then we add our
//badge to it by merging it via a NetBeans API utility method:</b>
public Image getIcon(int type) {
DataFolder root = DataFolder.findFolder(FileUtil.getConfigRoot());
Image original = root.getNodeDelegate().getIcon(type);
return ImageUtilities.mergeImages(original, smallImage, 7, 7);
}
public Image getOpenedIcon(int type) {
DataFolder root = DataFolder.findFolder(FileUtil.getConfigRoot());
Image original = root.getNodeDelegate().getIcon(type);
return ImageUtilities.mergeImages(original, smallImage, 7, 7);
}
}</pre> </li>
<li>Right-click this icon and save it in the main package of your module: <img alt="" src="../../images/tutorials/projectextensions/webPagesBadge.gif" /></li>
</ol>
<!-- ======================================================================================= -->
<h2><a name="extendingthecustomizer"></a>Extending the Project Customizer</h2>
<p>Finally, we create two new tabs in the Project Properties dialog of the web application project type.</p>
<ol>
<li><p>Create a Java class called <tt>ImportantFilesCustomizerTab</tt>.</p></li>
<li><p>Change the default code to the following:</p>
<pre class="examplecode">public class ImportantFilesCustomizerTab implements ProjectCustomizer.CompositeCategoryProvider {
private static final String MURPHY1 = "Murphy1";
private static final String MURPHY2 = "Murphy2";
private ResourceBundle bundle = NbBundle.getBundle(ImportantFilesCustomizerTab.class);
private String name;
@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-web-project", position = 100)
public static ImportantFilesCustomizerTab createMurphy1() {
return new ImportantFilesCustomizerTab(MURPHY1);
}
@ProjectCustomizer.CompositeCategoryProvider.Registration(projectType = "org-netbeans-modules-web-project", position = 110)
public static ImportantFilesCustomizerTab createMurphy2() {
return new ImportantFilesCustomizerTab(MURPHY2);
}
private ImportantFilesCustomizerTab(String name) {
this.name = name;
}
@Override
public Category createCategory(Lookup lkp) {
ProjectCustomizer.Category toReturn = null;
if (MURPHY1.equals(name)) {
toReturn = ProjectCustomizer.Category.create(
MURPHY1,
bundle.getString("LBL_Config_Murphy1"),
null);
} else {
toReturn = ProjectCustomizer.Category.create(
MURPHY2,
bundle.getString("LBL_Config_Murphy2"), // NOI18N
null);
}
return toReturn;
}
@Override
public JComponent createComponent(Category category, Lookup lkp) {
String nm = category.getName();
if (MURPHY1.equals(nm)) {
JPanel jPanel1 = new JPanel();
jPanel1.setLayout(new BorderLayout());
jPanel1.add(new JLabel(bundle.getString("LBL_Config_Murphy1")), BorderLayout.CENTER);
return jPanel1;
} else {
JPanel jPanel2 = new JPanel();
jPanel2.setLayout(new BorderLayout());
jPanel2.add(new JLabel(bundle.getString("LBL_Config_Murphy2")), BorderLayout.CENTER);
return jPanel2;
}
}
}</pre> </li>
<li><p>Add the keys referred to above to the <tt>Bundle.properties</tt>
file in the main package of your module:</p>
<pre class="examplecode">LBL_Config_Murphy1=Murphy 1
LBL_Config_Murphy2=Murphy 2 </pre> </li>
</ol>
<!-- ===================================================================================== -->
<h2><a name="building"></a>Installing the Module</h2>
<p>Finally, we install the module and make use of the result.</p>
<div class="indent">
<ol>
<li><p>Check that the module looks as follows
in the Projects window:</p>
<p><img src="../../images/tutorials/projectextensions/proj-window-69.png" alt="finished project"/></p></li>
<li>Right-click the module project and install it.</li>
<li><p>Create a new web application, or open an
existing one, and notice that it
has an Important Files node, containing the files
from the 'nbproject' folder:</p>
<p><img src="../../images/tutorials/projectextensions/result-69.png" alt="installed result"/></p></li>
<li><p>Right-click the web application project and choose Properties.
In the Project Properties dialog box, notice your new tabs:</p>
<p><img src="../../images/tutorials/projectextensions/proj-props-69.png" alt="installed result"/></p></li>
</ol>
</div>
<div class="feedback-box"><a href="https://netbeans.org/about/contact_form.html?to=3&amp;subject=Feedback:%20Project%20Extension%20Module%20Tutorial">Send Us Your Feedback</a></div>
<!-- ======================================================================================== -->
<h2><a name="nextsteps"></a>Next Steps</h2>
<p>For more information about creating and developing NetBeans modules, see the following resources: </p>
<ul>
<li><a href="https://netbeans.org/kb/trails/platform.html">Other Related Tutorials</a></li>
<li><a href="https://netbeans.org/download/dev/javadoc/">NetBeans API Javadoc</a></li>
</ul>
</body>
</html>