The following blog entry will take you through the creation of a
NetBean 6.1 (although the principal is the same for other versions)
Plug-in Module that will allow you to search all Jar files in a
specified directory structure for a given Class name or part there of.
On completion of this short tutorial you will have created a new
Toolbar button and Menu item that will open a Search tab within the
editor window. This will allow you to enter the Class Name to search
for and the starting directory. If you would simply like a copy of the
NBM then it can be found on the NetBeans Plugin Portal at http://plugins.netbeans.org/PluginPortal/faces/PluginDetailPage.jsp?pluginid=15286.
Resources
If you have been developing Java for a while you have probably come across the situation where you need to find a class you have used but it does not exist in your CLASSPATH. Well to resolve this I build a simple NetBeans Plugin (originally in NB 5) and have since upgraded it to NB 6.1.
The Jar Class Search Plugin, below, adds a new Menu item to the Toolbar Edit Menu and a new button to the Edit Toolbar. When either of these is selected the Jar Search tab will be opened within the Edit area of Netbeans. The user can then type in the name (or part of the name) of the Class they wish to search for and the starting directory. In addition the you can choose to search just the specified directory or recursively through all sub-directories and display all the jars that contain the specified Class or just the first.
Once the criteria have been entered you will be able to select Search and the Plugin will Search all Jars found for the Class and display the results in the Table.
To create the Module you will need to follow the steps below.
We now need to modify the JarClassSearchTopComponent.java so that it displays the fields we need as follows:

New Properties / Methods
Button Action Code
Constructor Change
You will notice from the above code that we need to additional classes and these should be created in the com.aph.jar.search.util.swing package.
Resources
Module Overview
If you have been developing Java for a while you have probably come across the situation where you need to find a class you have used but it does not exist in your CLASSPATH. Well to resolve this I build a simple NetBeans Plugin (originally in NB 5) and have since upgraded it to NB 6.1.
The Jar Class Search Plugin, below, adds a new Menu item to the Toolbar Edit Menu and a new button to the Edit Toolbar. When either of these is selected the Jar Search tab will be opened within the Edit area of Netbeans. The user can then type in the name (or part of the name) of the Class they wish to search for and the starting directory. In addition the you can choose to search just the specified directory or recursively through all sub-directories and display all the jars that contain the specified Class or just the first.
Once the criteria have been entered you will be able to select Search and the Plugin will Search all Jars found for the Class and display the results in the Table.
Creating the Module
To create the Module you will need to follow the steps below.
- File->New->Project->NetBeans Modules->Module

- Next
- Name and Location Page
- Next
- Module Configuration Page
- Code Name Base : com.aph.jar.search
- Module display Name : JarClassSearch
- Localizing Bundle : com/aph/jar/search/Bundle.properties
- XML Layer : com/aph/jar/search/layer.xml

- Finish
Supporting Files
Once the project has been create we will need to copy a number of utility classes and icons into the project structure. These will be used to associate the desired icon with the menu action and also process the searching of the directory and Jars to find those containing the class. All source for these can be found in the project Zip in the resources section below. We now need to create three new packages:- com.aph.jar.search.util.file
- com.aph.jar.search.util.swing
- com.aph.jar.search.icon
- jar_view.png
- jar_view16.png
- jar_view24.png
- FileUtils.java
- JarUtils.java
- ArchiveFileUtils.java
- AchiveBuildException.java
- ArchiveExtractionException.java
Windows Components and Actions
Now that we have created the associated files that will search through the specified directory and all jar files found we need to create a Windows Component and Action that will use them. This is achieved as follows:- Right Click on the com.aph.jar.search package and select
New->Windows Component

- Basic Settings Page
- Next
- Name, Icon and Location Page
- Finish
- JarClassSearchAction.java (Example Action Class)
- JarClassSearchTopComponent.java (The actual window that will be displayed)
- JarClassSearchTopcomponentSettings.xml
- JarClassSearchTopComponentWstcref.xml
We now need to modify the JarClassSearchTopComponent.java so that it displays the fields we need as follows:

- Open JarClassSearchTopComponent.java
- Add JPanel, from the Palette, to the TopComponent.
- Name : topLevelPanel
- Layout : BowLayout - Page Axis
- Add JPanel
- Name : searchCriteriaPanel
- Layout : GridLayout - 3 Columns
- Border : Etched
- Add JLabel
- Text : Class Name :
- Add JTextField
- Name : tfClassname
- Text : String
- Maximum Size ; [2147483647, 25]
- Add JLabel
- Text : <Blank Text>
- Add JLabel
- Text : Start Directory
- Add JTextField
- Name : tfSearchRoot
- Text : /
- Maximum Size : [2147483647, 25]
- Add JButton
- Name : btnBrowse
- Text : Browse
- Add JLabel
- Text : <Blank Text>
- Add JPanel
- Layout : BoxLayout - Line Axis
- Add JCheckBox
- Name : cbRecursive
- Text : Recursive
- Add JCheckBox
- Name : cbShowAll
- Text : Show All
- Add JButton
- Name : btnSearch
- Text : Search
- Add JPanel
- Name : resultPanel
- Layout : BoxLayout - Page Axis
- Border : Etched
- Add JTable (This will automatically create a JScrollPane)
- Name : tblJars
- Create Button Actions for the two button (Double Click on them) and modify the code as follows.
New Properties / Methods
| //
Properties protected String classname = ""; protected String rootDirectoryName = ""; protected boolean recursive = false; protected boolean showAll = true; protected JarTableModel jarTableModel = new JarTableModel(); protected SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yyyy HH:mm:ss"); protected class SearchJarRunThread implements Runnable { public void run() { try { clearJarTable(); JarUtils jarUtils = new JarUtils(); File[] files = jarUtils.getSubFiles(rootDirectoryName, recursive); Object[] row = new String[JarTableModel.COLUMNS]; String classnameInJar = null; if (files != null) { for (int i = 0; i < files.length; i++) { if (jarUtils.getExtension().equals(jarUtils.getExtension(files[i]))) { if (jarUtils.isFileInArchieve(classname, files[i].getAbsolutePath())) { classnameInJar = jarUtils.getClassnameInArchive(); System.out.println(files[i].getAbsolutePath() + " (" + classnameInJar + ")"); if (classnameInJar.endsWith(".class")) { row = new String[JarTableModel.COLUMNS]; row[0] = files[i].getAbsolutePath(); row[1] = classnameInJar.replaceAll("/", "."); row[2] = sdf.format(new Date(files[i].lastModified())); row[3] = Long.toString(files[i].length()); jarTableModel.addRow(row); if (!showAll) { break; } } } } } } } catch (Exception ex) { Exceptions.printStackTrace(ex); } } } // Methods private void postInitComponents() { // Set Layouts //searchPanel searchCriteriaPanel.setLayout(new SpringLayout()); SpringUtilities.makeCompactGrid(searchCriteriaPanel, 3, 3, // Rows, Columns 0, 0, // Initial X, Initial Y 10, 10); // X Pad, YPad //topLevelPanel topLevelPanel.setLayout(new SpringLayout()); SpringUtilities.makeCompactGrid(topLevelPanel, 2, 1, 0, 10, 10, 10); // Set Table Model tblJars.setModel(jarTableModel); clearJarTable(); tblJars.getSelectionModel().addListSelectionListener(new RowListener()); // TopComponent setLayout(new SpringLayout()); SpringUtilities.makeCompactGrid(this, 1, 1, 0, 0, 0, 0); // Get Settings String classname = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.CLASSNAME_KEY, ""); String searchRoot = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.SEARCH_ROOT_KEY, ""); String recursiveString = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.RECURSIVE_KEY, Boolean.toString(JarClassSearchConstantsInterface.RECURSIVE_DEFAULT)); String showAllString = Preferences.userNodeForPackage(JarClassSearchTopComponent.class).get(JarClassSearchConstantsInterface.SHOWALL_KEY, Boolean.toString(JarClassSearchConstantsInterface.SHOWALL_DEFAULT)); tfClassname.setText(classname); tfSearchRoot.setText(searchRoot); cbRecursive.setSelected(Boolean.parseBoolean(recursiveString)); cbShowAll.setSelected(Boolean.parseBoolean(showAllString)); } protected void clearJarTable() { for (int i = jarTableModel.getRowCount() - 1; i >= 0; i--) { jarTableModel.removeRow(i); } } |
Button Action Code
| private
void btnBrowseActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: javax.swing.JFileChooser fileChooser = new JFileChooser(tfSearchRoot.getText()); fileChooser.setMultiSelectionEnabled(false); fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { tfSearchRoot.setText(fileChooser.getSelectedFile().getAbsolutePath()); } } private void btnSearchActionPerformed(java.awt.event.ActionEvent evt) { // TODO add your handling code here: recursive = cbRecursive.isSelected(); showAll = cbShowAll.isSelected(); classname = tfClassname.getText().trim(); rootDirectoryName = tfSearchRoot.getText().trim(); // Save current values as last used Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.CLASSNAME_KEY, tfClassname.getText()); Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.SEARCH_ROOT_KEY, tfSearchRoot.getText()); Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.RECURSIVE_KEY, Boolean.toString(cbRecursive.isSelected())); Preferences.userNodeForPackage(JarClassSearchTopComponent.class).put(JarClassSearchConstantsInterface.SHOWALL_KEY, Boolean.toString(cbShowAll.isSelected())); SearchJarRunThread runThread = new SearchJarRunThread(); RequestProcessor.getDefault().post(runThread); } |
Constructor Change
| private
JarClassSearchTopComponent() { initComponents(); setName(NbBundle.getMessage(JarClassSearchTopComponent.class, "CTL_JarClassSearchTopComponent")); setToolTipText(NbBundle.getMessage(JarClassSearchTopComponent.class, "HINT_JarClassSearchTopComponent")); setIcon(Utilities.loadImage(ICON_PATH, true)); postInitComponents(); } |
You will notice from the above code that we need to additional classes and these should be created in the com.aph.jar.search.util.swing package.
- JarTableModel.java - Defines the layout / column titles of the display table
- SpringUtililties.jar
- Lays out the SpringLayout we set the in the Panels.
Menu / Button Action
Now we have created the display component for the Module we need to add the Action that will be displayed in the Edit Menu and as a Button in the Edit Toolbar. This can be done in two ways.- Edit the layer.xml and associated files to add the
TopComponentAction
- Add a new Action and copy the code from the example action.
- Delete the JarClassSearchAction.java (Copy Code first)
- Right Click the top level package and New-Action

- Action Type
- Next
- GUI Registration
- Category : Edit
- Global Menu Item : checked
- Menu : Edit
- Global Toolbar Button : Checked
- Toolbar : Edit

- Next
- Name, Icon and Location
- Finish
- This will create the JarClassSearchAction.java file and modify
the layer.xml and Bundle.properties.
- Take the previously copied performAction method and replace the
one generated as follows.
package com.aph.jar.search;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction;
import org.openide.windows.TopComponent;
public final class JarClassSearchAction extends CallableSystemAction {
public void performAction() {
TopComponent win = JarClassSearchTopComponent.findInstance();
win.open();
win.requestActive();
}
public String getName() {
return NbBundle.getMessage(JarClassSearchAction.class, "CTL_JarClassSearchAction");
}
@Override
protected String iconResource() {
return "com/aph/jar/search/icon/jar_view.png";
}
public HelpCtx getHelpCtx() {
return HelpCtx.DEFAULT_HELP;
}
@Override
protected boolean asynchronous() {
return false;
}
}












