Overview

# Contents

- Introduction
- The API Changes List
- Changes in Implementation Behavior and in Module APIs
- 3.6 -> 4.0 Upgrade Guide
  - Notable Incompatibilities and Required Changes
    - Module JARs no longer autoscanned
    - Execution API split in half
    - Java Comparators separation
  - Desirable Changes in Modules
- 3.5 -> 3.6 Upgrade Guide
  - Notable Incompatibilities and Required Changes
    - Window system reimplementation
    - Ensure the correct PropertyEnv instance controls a custom editor dialog
    - Loaders threading semantics are now more strict
    - PropertyPanel does not guarantee caching of property editors
    - BookmarksAction and BookmarksNode no longer installed
  - Desirable Changes in Modules
    - Upgrade to JavaHelp 2.0
    - Actions should run in the event thread
    - Order of `Node.Property`s in a `Node.PropertySet` is significant
    - Window System XML layer declarations changed
    - `TopComponent` subclasses should override `getPersistenceType()`
    - `TopComponent` subclasses should override `preferredID()`
    - TopComponent activation
    - TopComponent focus management
    - Prefer `Node.Property` to `PropertyModel`
    - Specific help IDs for Nodes' property sheets
    - Use regular expressions from the JRE
- 3.4 -> 3.5 Upgrade Guide
  - Notable Incompatibilities and Required Changes
    - Group functionality moved to separate module
    - Open APIs Separation and Deprecation
    - Indirect dependencies do not count for a module's "effective classpath"
  - Desirable Changes in Modules
    - Use `InstalledFileLocator`
    - Use `EditorCookie.Observable`
- 3.3 -> 3.4 Upgrade Guide
  - Notable Incompatibilities
    - XML MIME types
    - Use of libraries from classpath
  - Desirable Changes in Modules
    - Declare public packages
    - Purify execution classpath
    - Require a JavaHelp implementation
    - Move manifest nodes to layers
    - `RequestProcessor` API changes
    - Enable auto update of module without restart
    - Add a description for the selected node in the Explorer
    - JAR Packager - registration of `ArchiveBuilder`s, extended properties moved to layer
    - Change in format of `DataShadow`s
    - Eager modules
    - Use new open/close/show/hide methods for `TopComponent`
    - Provide final children list for a node
    - Supply `TemplateWizard.Iterator` as a cookie
    - Map file objects to URLs
    - Adjust New wizard template folder order
    - Stop using FileSystemCapabilities
- 3.2 -> 3.3 Upgrade Guide
  - Notable Incompatibilities
  - Desirable Changes in Modules
    - Move settings to layers
    - Define workspaces and windows in layers
    - Avoid persisting closed `TopComponent`s
    - Localize manifests with bundles
    - Install JavaHelp help sets with layers
    - Ability to turn modules on and off, list all modules
    - Use annotations to control GUI of editor
    - Define file types using MIME resolvers
    - Lazy instances with `InstanceCookie.Of`
    - Enhanced lookup facilities supersede service types
    - XML entity resolution and processors installed via layer
    - Autoload modules
    - Use hints to control property editors
  - Desirable Performance Optimizations
    - DataLoader changes
    - SystemOption usage
    - Services declaration
    - WindowSystem changes
    - ModuleInstall cleanup
    - BeanInfo implementations
    - PropertySupport
    - Static resource bundles
- Pre-3.3 Changes
  - Desirable Changes in Modules
    - Image caching and badging
    - Short and long descriptions and categories for modules
    - Nicer-looking wizards
    - Use `ErrorManager` for logging
- Helpful Performance Tools
  - Startup performance logging
  - Class loading listing

## Introduction

Module developers who have stable and tested modules developed against an earlier NetBeans release should in most cases be able to use them unmodified in a newer NetBeans release due to API compatibility. However improvements are often made, which module developers are encouraged to take advantage of to ensure the best integration into the new release. This document is an attempt to point out the most significant changes and how a typical module should be modified to take advantage of them, including some examples and tutorials. The best sources of examples are of course those modules shipped as part of NetBeans as in most cases these have already been upgraded to match the new APIs.

These recommendations are cumulative: for example, if you are upgrading from 3.2 straight to 3.4, check both the 3.2 -> 3.3 upgrade section and the 3.3 -> 3.4 upgrade section.

Minor local changes to APIs are not listed; interested developers can read through the complete change list if necessary (see next section).

## The API Changes List

The definitive source of information is the API changes list. This summarizes all known Open APIs changes, big and small. For the most part you as a module developer do not need to read all this, because many of the changes simply will not be of interest to you.

Two things are important. One, if you are in fact using a new API, this document will tell you which version of the APIs to depend on in the list of changes by version. For the Open APIs, you must use `OpenIDE-Module-IDE-Dependencies` when making use of a newly added API call.

Two, there are a handful of incompatible changes which everyone should be aware of. See the list of incompatible changes.

## Changes in Implementation Behavior and in Module APIs

This guide may be used to list changes in implementation behavior which are likely to be of interest to module developers, even while the official API specification has not changed. Always consult the official documentation for details on what the API really guarantees.

Useful information in the Open APIs documentation which is not guaranteed by the specification is shown with a blue bar in the left margin like this.

Modules can also provide their own APIs, including reference documentation and API change lists. Significant changes to module APIs may be listed here if they are likely to affect many developers. Visit a module's web site for more information.

# 3.6 -> 4.0 Upgrade Guide

This upgrade guide outlines notable API changes between NetBeans 3.6 and 4.0.

PENDING: need to link to documentation of 4.0 build system. When ready will be http://projects.netbeans.org/buildsys/howto.html Also to summaries of how to use JMI in place of org.openide.src. And info on new debugger APIs. Also http://platform.netbeans.org/articles/installation.html Also no more mounting, etc.

## Notable Incompatibilities and Required Changes

Check for changes here which might cause problems for your module if left uncorrected.

### Module JARs no longer autoscanned

In NetBeans 3.x, the module system would always check during startup for new JAR files in the `modules/` subdirectory of the installation (also `modules/eager/` and `modules/autoload/`). At the same time, the actual module configuration was controlled by XML files in the `Modules/` subdirectory of the system file system (e.g. `system/` subdirectory of the NetBeans installation or user directory), as mentioned in the Modules API. If the module system found a new JAR file in an autoscanned directory with no existing config file, it would create a fresh config file for it (trying to enable it), and run `ModuleInstall.installed()`. However module authors were strongly encouraged to create the proper config files in advance, so that the module configuration would already be correct and autoscanning would normally be a no-op, except after adding JARs from Auto Update or by manual copying.

As of NetBeans 4.0, this autoscanning functionality has been removed, which simplifies the module system, saves a bit of time during startup, and gives more flexibility to product assemblers since they are in full control of the module configuration. However this means that including a config file with your module is now mandatory. A config file can be written by hand, or created by the `<createmodulexml>` task (as is done automatically for projectized modules). The config file should be included in your product's installation, if you are shipping a complete product; or included in your module's NBM file, if you are distributing just an NBM. (To preserve some backward compatibility, the AutoUpdate client may attempt to create a config file for an NBM which does not include one, but this is not reliable - always supply one explicitly.)

Here is an example of a configuration file for the "beans" module, located in `ide5/config/Modules/org-netbeans-modules-beans.xml`:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE module PUBLIC "-//NetBeans//DTD Module Status 1.0//EN"
                            "http://www.netbeans.org/dtds/module-status-1_0.dtd">
    <module name="org.netbeans.modules.beans">
        <param name="autoload">false</param>
        <param name="eager">false</param>
        <param name="enabled">true</param>
        <param name="jar">modules/org-netbeans-modules-beans.jar</param>
        <param name="release">1</param>
        <param name="reloadable">false</param>
        <param name="specversion">1.14</param>
    </module>

This module is declared to be a regular (not autoload or eager) module, and asked to be enabled. The path to the JAR file is given (within the `ide5` module cluster), and some information about the module version is given. The above file would have been created by an Ant target similar to this:

    <project default="run">
        <property name="nbantext.jar" location="..../nbbuild/nbantext.jar"/>
        <property name="cluster.dir" location="..../nbbuild/netbeans/ide5"/>
        <taskdef name="createmodulexml" classname="org.netbeans.nbbuild.CreateModuleXML">
            <classpath>
                <pathelement location="${nbantext.jar}"/>
            </classpath>
        </taskdef>
        <target name="run">
            <createmodulexml xmldir="${cluster.dir}/config/Modules">
                <enabled dir="${cluster.dir}">
                    <include name="modules/org-netbeans-modules-beans.jar"/>
                </enabled>
            </createmodulexml>
        </target>
    </project>

### Execution API split in half

As part of the move to an Ant-based build system in NetBeans 4.0, much of the 3.6 Execution API is no longer necessary. The deprecated portion was moved to a new module (`openide/execution/deprecated` in CVS). Modules with a dependency on the non-deprecated classes need to upgrade their dependency declaration to

    OpenIDE-Module-Module-Dependencies: org.openide.execution > 1.2

(or later). The deprecated API is still available as

    OpenIDE-Module-Module-Dependencies: org.openide.execution.deprecated > 1.0

but this module is not shipped with the standard NetBeans IDE or platform.

Non-deprecated classes still available and potentially useful in 4.0 (with some additions and deprecations) include:

- `org.openide.execution.ExecutionEngine`
- `org.openide.execution.ExecutorTask`
- `org.openide.execution.NbClassLoader`
- `org.openide.execution.NbClassPath` (factory methods deprecated however)
- `org.openide.execution.ScriptType` (not useful without `scripting` module however, which is no longer supported)

Deprecated classes include:

- `org.openide.actions.ExecuteAction`
- `org.openide.cookies.ArgumentsCookie`
- `org.openide.cookies.ExecCookie`
- `org.openide.execution.ExecInfo`
- `org.openide.execution.Executor`
- `org.openide.execution.ExecutorType`
- `org.openide.execution.NbfsStreamHandlerFactory` (also see Javadoc for information on deprecated URL protocols: `nbresboot`, `nbresbootloc`, `nbrescurr`, `nbrescurrloc`)
- `org.openide.execution.NbfsURLConnection` (`nbfs` URL protocol still available via other means, but not widely used in 4.0)
- `org.openide.execution.ProcessExecutor`
- `org.openide.execution.ThreadExecutor`
- `org.openide.loaders.ExecutionSupport`

More information:

- (non-deprecated) Execution API
- Deprecated Execution API

### Java Comparators separation

Skip if your module does not depend on the java module (`org.netbeans.modules.java`).

The Comparators API (`org.netbeans.api.java.comparators`) was moved from the java module to the org.openide.src module. So modules that do not use it and depend on the java module are required to update their dependency on the java module to specification version 1.17 to prevent warnings in console.

Modules that use comparators have to declare their dependency on the org.openide.src module with spec version 1.3 and remove dependency on the java module or update it as was mentioned above.

## Desirable Changes in Modules

You should look through changes in this section and see if they might apply to your module. If so, your module will be a better citizen of NetBeans 4.0 by making the recommended changes.

# 3.5 -> 3.6 Upgrade Guide

This upgrade guide outlines notable API changes between NetBeans 3.5 and 3.6.

## Notable Incompatibilities and Required Changes

Check for changes here which might cause problems for your module if left uncorrected.

### Window system reimplementation

The window system has been completely reimplemented. The old API remains binary compatible, but the significant UI changes required some changes in the window system APIs. There are a fair number of the APIs which have been deprecated, and new ones and replacements added; the retained APIs may not behave exactly like their older counterparts. Of particular importance is that access to almost all of the window system APIs must now be performed only on the AWT event dispatch thread. See the summary of the API changes in changes document and also especially XML layer declarations changes which is supposed to be the only (must-have) required change, it is found in the same doc.

### Use regular expressions from the JRE

J2SE 1.4 includes its own regular expression support in the `java.util.regex` package. You should use this instead of the Apache Regexp library. Making the transition is not generally difficult:

1. Remove any package dependencies on `org.apache.regexp`, or module dependencies on `org.netbeans.libs.regexp`, from your module's manifest. Remove `regexp.jar` from your compile-time classpath.

2. Rather than `RE`, use `Pattern`.

3. Rather than `RECompiler` and `REProgram`, just use `Pattern.compile`. `PatternSyntaxException` should be caught if the regexp was entered by the user or otherwise might be erroneous. You can pass flags (such as case-insensitive) to `compile`, or embed them in the regexp itself.

4. Rather than `RE.match(String)`, use `Pattern.matcher(String).find()`. Note that `Matcher.matches()` means that the whole string must match (anchored at both ends).

5. If you are looking for multiple matches, or wish to retrieve captured groups etc., just make the `Matcher` and then call `find()`, `start(int)`, `end(int)`, `group(int)`, etc.

6. Rather than using `StreamCharacterIterator` or `ReaderCharacterIterator` to parse a file, memory-map it into a byte buffer using NIO, make a `CharBuffer` from that, and match on it.

7. If you need to parse from an open-ended stream, it is trickier. You may try something like the following: `ReaderCharSequence`

### Ensure the correct PropertyEnv instance controls a custom editor dialog

If you have been using `ExPropertyEditor` and `PropertyEnv` to control the OK/Cancel buttons on custom editor dialogs, note that `attachEnv` may be called more than once with different instances of `PropertyEnv`. If the custom editor is invoked more than once, ensure that the `PropertyEnv` the custom editor is setting the state on to control the dialog buttons is the instance passed to attachEnv immediately prior to opening the custom editor, not a cached instance from a previous dialog.

Ensure any listeners are detached from the previous PropertyEnv on subsequent calls to `attachEnv()`.

### Loaders threading semantics are now more strict

Constructors of `DataObject`s should not do too many things. In release36 when a constructor of a data object is running, all other threads are prevented from accessing files in the same folder to prevent calls to not yet constructed data object. This is a fix for a bug that used to be called "500ms problem".

Generally it is suggested to prevent all modifications to files (writing, deleting, renaming, etc.) in data object constructors.

### PropertyPanel does not guarantee caching of property editors

`PropertyPanel` will no longer necessarily cache the `PropertyEditor` whose contents it is displaying. The method `getPropertyEditor()` has been deprecated. It will now fetch the property editor from the property it is displaying as needed. To ensure consistent access to the same property editor instance, the `Node.Property` supplying it must handle any caching necessary. `ReaderCharSequence`

### BookmarksAction and BookmarksNode no longer installed

BookmarksAction and BookmarksNode no longer installed by the Utilities module, also meaning that the Help/Bookmarks menu is gone. If you have added bookmarks to the bookmarks submenu, add them directly to the Help menu instead.

## Desirable Changes in Modules

You should look through changes in this section and see if they might apply to your module. If so, your module will be a better citizen of NetBeans 3.6 by making the recommended changes.

### Actions should run in the event thread

Any subclasses of `CallableSystemAction` should override `asynchronous`:

    protected boolean asynchronous() {
        return false;
    }

and ensure that `performAction` is expecting to be run in the event thread. Direct subclasses of `SystemAction` or `Action` should expect to be have `actionPerformed` called in the event thread. The action may explicitly do its work in a separate thread (e.g. using `RequestProcessor`) if it needs to.

See: issue #35755.

### Upgrade to JavaHelp 2.0

NetBeans now bundles with JavaHelp 2.0 software, which enables better merging of the TOC and index. These are the most important things to adjust for:

- Since the TOC can be better merged now, the Help | Help Sets menu should no longer be used. This entails deleting the Help folders in Actions and Menu in your module's layer file. See Making the Help Set Known to the IDE for more information.
- DO NOT use manual separators in your indexes, (e.g. <indexitem text="-A-"></indexitem>). These are superfluous with merged indexes are suspected of triggering a bug in JH that crashes the help system - see Issuezilla bug 39966.
- See Merge Hints for TOC and Index for more information on tailoring your TOC and index to seamlessly merging with those of other help sets.

See the JavaHelp release notes for more information on the JavaHelp 2.0 software release.

### Order of `Node.Property`s in a `Node.PropertySet` is significant

As detailed in issue #21065, the order of properties in a property set (formerly property sheet tab, now property sheet category) is now significant; the property sheet will not automatically alphabetize properties for you. If your module produces nodes with more than one property in a given property set, pay attention to the order, and manually adjust it if you prefer.

### Window System XML layer declarations changed

As detailed at Changes in XML layer declarations, it is necessary to use the newer version of the XML declaration, especially declaration of modules, to be able achieve the desired layout whitin the new UI hierarchy of new window system implementation.

### `TopComponent` subclasses should override `getPersistenceType()`

Override `TopComponent.getPersistenceType` instead of using the deprecated client property "persistenceType". For example if you set client property PersistenceType to "never" (the window system should not store the position and contents of your TopComponent) in NB 3.5, you should override `TopComponent.getPersistenceType` to return the constant `TopComponent.PERSISTENCE_NEVER`. This property determines if, and when, the window system will store the state of your TopComponent (where it was docked, etc.).

Even if you did not set any value for the persistence type in the past, it is recommended to add this override to explicitly indicate how your `TopComponent` should be persisted. For backward compatibility, the default persistence type is `TopComponent.PERSISTENCE_ALWAYS`. For transient views such as search results or other types of output, this is not the correct behavior.

Even if permanent persistence is the right thing for a `TopComponent`, it should override this method rather than relying on the default remaining the same in the future.

### `TopComponent` subclasses should override `preferredID()`

Override `TopComponent.preferredID` to tell window system ID string that identifies your `TopComponent`. It's good idea to always override this method to return some `String` name unique or special to your `TopComponent` subclass. Good starting point for your `preferredID` might be actual name of your TopComponent's subclass.

Window system uses preferredID result as part of unique TopComponent instance identification.

### TopComponent activation

`TopComponent.requestFocus` was used to both activate and focus `TopComponent`s in the old window system. As this caused problems, a new method, `TopComponent.requestActive`, was added. This method must be used to activate `TopComponent`s in window system, causing its parent `Mode`s to indicate activation, and causing context-sensitive actions to be enabled/disabled appropriately. `requestActive` will cause focus to be transferred to the `TopComponent` by calling `TopComponent.requestFocusInWindow`. Do not call `TopComponent.requestFocus` in isolation - it will focus to the `TopComponent` but will not activate the `TopComponent`, leaving the window system in an inconsistent state.

### TopComponent focus management

If your `TopComponent` subclass overrides `requestFocus` to transfer focus to a subcomponent, it should also override `requestFocusInWindow`. The window system now uses `requestFocusInWindow` to focus `TopComponent` to avoid infinite loops when the WINDOW_ACTIVATED event is handled in SDI mode.

`java.awt.Component.requestFocusInWindow` is new in JDK 1.4. Generally it is good idea to override `requestFocusInWindow` in `Component` subclasses if you override `requestFocus`. For an example, see `org.netbeans.core.NbMainExplorer.ExplorerTab`. It is subclass of `TopComponent` and it overrides both `requestFocus` and `requestFocusInWindow`. `ExplorerTab` uses a JTree as subcomponent which should be the final recipient of focus.

### Specific help IDs for Nodes' property sheets

It is now possible to provide help IDs specific to the properties of Nodes, distinct from the help ID for the node itself, via `Node.getValue ("propertiesHelpID")`. Help IDs may also be specified for individual property sets via `PropertySet.getValue("helpID")`. Only the first property set displayed is checked for this value. If your module contributes properties to another module's node, and you want to provide help specific to your properties, specify that your properties should be displayed on a different tab in the property sheet by returning a localized tab name from `PropertySet.getValue("tabName")` for those property sets that you are providing. Returning the same name for multiple property sets will cause them to be grouped together on their own tab in the property sheet.

If no help ID is provided either by the selected property, the first property set displayed, or the node, the help button will be disabled. The help button in the property sheet will never display the help on the node, only property-specific help. This change only affects help button in the description area of the property sheet, the help item on the property sheet's popup menu, and the help ID chosen if the user presses F1 while the property sheet has focus.

### Prefer `Node.Property` to `PropertyModel`

With the property sheet rewrite, PropertyPanel is now driven primarily by `Node.Property` objects; use of `PropertyModel` is discouraged except in the specific circumstance of needing to display a property whose value may unexpectedly change due to events beyond the control of the UI. For uses of `DefaultPropertyModel`, use `PropertySupport.Reflection` instead.

# 3.4 -> 3.5 Upgrade Guide

This upgrade guide outlines notable API changes between NetBeans 3.4 and 3.5.

## Notable Incompatibilities and Required Changes

Check for changes here which might cause problems for your module if left uncorrected.

### Group functionality moved to separate module

If your module brings `.group` files you should change dependency of your module. Currently you declare dependency on Utilities modules in module's manifest:

    OpenIDE-Module-Module-Dependencies: org.netbeans.modules.utilities/1

Group functionality was moved to separate `group.jar` module. You should change module's manifest to require `dataload.group` token:

    OpenIDE-Module-Requires: dataloader.group

I.e. remove `*-Module-Dependencies` and add `*-Requires` to module's manifest, see RMI's manifest for example.

### Open APIs Separation and Deprecation

Cleaning of the Open APIs by separating them into independent modules has progressed in several phases.

#### Phase I

Many classes in the Open APIs have been deprecated and moved to a separate module, `openide-deprecated.jar`. The Java Hierarchy API and a few associated classes were moved also to `java-src-model.jar`. The core implementations of deprecated APIs were moved to `core-deprecated.jar`.

Module developers who did not use any of the deprecated API classes to begin with, or who are able and willing to clean up their modules to not use them, should request:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 3.14

Otherwise they may compile against `openide-deprecated.jar` for the time being and declare:

    OpenIDE-Module-Module-Dependencies: org.openide.deprecated > 1.0
    OpenIDE-Module-Requires: org.openide.TopManager

Modules which wish to use the Java Hierarchy API may compile against `java-src-model.jar` and declare:

    OpenIDE-Module-Module-Dependencies: org.openide.src > 1.0

For compatibility, modules with no `IDE/1` dependency, or a dependency older than 3.14, will be automatically given the three dependencies above at runtime. The three new modules are autoloads, so they will only be loaded if at least one module requests them (explicitly or implicitly).

See the Open APIs Changes List for a complete list of classes and packages which were deprecated. The ones which were most commonly used are:

`org.openide.TopManager`

  All methods from this class are deprecated. Most of the getter methods can be replaced by using `Lookup.getDefault().lookup(InterfaceClass.class)`.

  Most utility methods, such as showing a URL, displaying status text, etc., have been replaced by separate utility classes with similar semantics, all of which have a `getDefault()` method:

  - `org.openide.DialogDisplayer`
  - `org.openide.LifecycleManager`
  - `org.openide.awt.HtmlBrowser.URLDisplayer`
  - `org.openide.awt.StatusDisplayer`
  - `org.openide.loaders.RepositoryNodeFactory`
  - `org.openide.nodes.NodeOperation`
  - `org.openide.windows.IOProvider`

  Showing help should be done using the JavaHelp API module.

  `systemClassLoader()` should be replaced with lookup on `ClassLoader.class`. `currentClassLoader` has no undeprecated equivalent, since it misuses the Java classpath; for now, use `NbClassLoader` (you may wish to add `AllPermissions` using `setDefaultPermissions`).

  For details on replacing `TopManager` calls, see its Javadoc.

  Forcible initialization of the NetBeans core using `TopManager.getDefault()` (in standalone applications, tests, and scripts) can in some cases be deleted, since many services are now available standalone. If it is necessary to force modules to be loaded, ask lookup for `ModuleInfo.class` to scan for and install modules, as well as performing other unspecified initialization activities in the core.

`org.openide.Places`

  Everything here is deprecated. To find folders, find them by file path on the system filesystem: `Repository.getDefault().getDefaultFileSystem()`. Most nodes are no longer made available to modules, as they are details of the GUI implementation, but see `RepositoryNodeFactory` for `repository()`.

`org.openide.debugger.*` and related cookies, actions, and `org.openide.loaders.ExecSupport`

  The Debugger API is deprecated, as it never really exposed the actual power of the `debuggercore` module. As of this writing, a full replacement is still pending. `ExecSupport` may be replaced by `org.openide.loaders.ExecutionSupport` which provides just the ability to select an `Executor`, without referring to debugger types.

`org.openide.cookies.ElementCookie` and `org.openide.loaders.DataObjectFilter`

  Ancient APIs used only by the old Object Browser. Should be replaced by the Looks API when available.

`org.openide.cookies.ProjectCookie` and related actions

  Will be obsoleted by the new projects system.

Many classes in `org.openide.explorer.propertysheet.editors.*`, and `org.openide.loaders.ExtensionListEditor`

  These property editor implementations are obsolete. Simply declare your properties to be of the correct type, and often a suitable editor will be found automatically. For cases where more control is needed, hints may be passed to the property editor implementation; see the Explorer API.

`org.openide.options.ControlPanel`, several classes in `org.openide.modules.*`, and `org.openide.actions.HelpAction`

  Various classes which have not been used in the APIs or core for some time and can be considered obsolete.

#### Phase II

The Compiler API is now in a separate module, `modules/autoload/openide-compiler.jar` at compile time, `org.openide.compiler > 1.0` at runtime. Any module wishing to call `CompilationEngine.getDefault()`, directly or indirectly, must declare a dependency on the token `org.openide.compiler.CompilationEngine` to ensure that the `core-compiler.jar` module is loaded.

The Execution API is in `modules/autoload/openide-execution.jar` at compile time, `org.openide.execution > 1.0` at runtime. Again, the token `org.openide.execution.ExecutionEngine` should be required by a module in order to guarantee that `ExecutionEngine.getDefault()` will succeed.

`InputOutput` and related classes dealing with the Output Window are now called the Input/Output API, separate from the Window System API. Use `modules/autoload/openide-io.jar`, `org.openide.io > 1.0`, and again `org.openide.windows.IOProvider` to ensure `IOProvider.getDefault()` will succeed.

Module authors are encouraged to determine which of the three above APIs they really need to use, and remove gratuitous dependencies. In particular, the Compiler API is likely to be deprecated by new Projects, so frivolous uses of this API should be removed sooner rather than later. If your module really needs all three APIs, your manifest could be updated as follows:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 3.17
    OpenIDE-Module-Module-Dependencies: org.openide.compiler > 1.0,
      org.openide.execution > 1.0, org.openide.io > 1.0
    OpenIDE-Module-Requires: org.openide.compiler.CompilationEngine,
      org.openide.execution.ExecutionEngine, org.openide.windows.IOProvider

The Terminal Emulator library is now `modules/autoload/terminalemulator.jar`; use a module dependency on `org.netbeans.lib.terminalemulator` rather than a package dependency.

To reduce the number of modules needing to depend on the Execution API, some deprecations and additions were introduced:

- Registration of URL stream handler factories using `NbfsStreamHandlerFactory.register(...)` is deprecated. Simply create an instance of `URLStreamHandlerFactory` and add it to Lookup instead.

- The method `FileUtil.nbfsURLStreamHandler` was added, but is not intended for use by modules.

- Direct use of `NbfsURLConnection` to encode and decode `nbfs` protocol URLs is deprecated in favor of the more general `URLMapper` from the Filesystems API.

The new method `AbstractCompileAction.prepareJobFor` ought to be used when creating a compiler job based on a folder, rather than assuming that `DataFolder` will have a `CompilerCookie`.

`Executor` subclasses need no longer override `execute(ExecInfo)`; `ExecInfo` has been deprecated (it is not classpath-safe). Executors must override `execute(DataObject)` instead. Callers should always use the `DataObject` form, never the `ExecInfo` form. Similarly, `DebuggerType` subclasses should override `startDebugger(DataObject,boolean)` and just implement `startDebugger(ExecInfo,boolean)` to throw an exception.

See the Open APIs Changes List for further details on the Phase II separation.

As with Phase I, old modules not depending on version 3.17 or later of the Open APIs will be given automatic dependencies on the separated APIs, for binary compatibility.

For more details, see issue #19443.

#### Phase III

The Debugger API is no longer deprecated in this phase, and is available in the new autoload module `debuggercore/oldapi/netbeans/modules/autoload/openide-debugger.jar`. This new module contains all of `org.openide.debugger.*`, plus `org.openide.cookies.DebuggerCookie` and `org.openide.loaders.ExecSupport`.

The module does not contain any actions. In the event that you were setting action performers for e.g. `ToggleBreakpointAction`, please note that the action implementations now reside in the `org.netbeans.modules.debugger.support.actions.*` package (in `debuggerCore.jar`); and that you need not refer directly to the action in order to set a performer - rather, modify the action map for your `TopComponent` (or other component) to bind e.g. `"org.netbeans.modules.debugger.support.actions.ToggleBreakpointAction"` to a `javax.swing.Action` of your choice. This is easier and safer than setting and unsetting action performers.

Modules should declare a dependency:

    OpenIDE-Module-Module-Dependencies: org.openide.debugger > 1.0

Any modules depending on `org.openide.deprecated` prior to version `1.2` will receive this dependency automatically.

You may if you wish also:

    OpenIDE-Module-Requires: org.openide.debugger.Debugger

in case your module cannot work without a debugger implementation being installed.

For more details, see issue #29914.

### Indirect dependencies do not count for a module's "effective classpath"

In NetBeans 3.4, if module A exposes some API packages (either explicitly using `OpenIDE-Module-Public-Packages`, or implicitly by omitting this attribute entirely), and module B depends on module A, and module C depends on module B, then module C can directly refer to those packages in A. In NetBeans 3.5, this is no longer permitted; if C really wishes to refer to classes in A, it must declare an explicit dependency on A as well as on B.

This change makes the "effective classpath" for a module more apparent: just look at the listed dependencies in its manifest. It also permits B in this example to use A's API as an implementation detail: B may be exposing its own API and only using A to implement it, but not wish to expose this fact to clients. In NetBeans 3.5, B can use any other modules to implement itself without fear of "polluting" its own public API. Its clients could even use a different version of A's packages for their own purposes. If B does wish to include A's Java-level API as part of its own, it should simply state in its documentation that clients may need to declare a dependency on A as well as on B.

Similarly, in NetBeans 3.4, if module A declared some package dependencies on JARs in the startup classpath - for example `regexp.jar` - not only could A access these classes, but any module depending on A could access them too. In 3.5, modules can only access startup classpath packages they themselves declare an explicit dependency on.

For compatibility reasons, modules with no API dependency declaration, or depending only on APIs version 3.11 or earlier, will see the 3.4 behavior: they will be permitted to access modules they only depend on indirectly, or packages they only depend on via a module dependency. But modules declaring:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 3.12

will see the new 3.5-style behavior.

To check whether your module is correctly declaring every dependency, make sure your `bin/ide.cfg` does not contain `-J-Xverify:none` (dev builds are OK, but change this in release builds), then start NetBeans with the flag `-J-Dnetbeans.preresolve.classes=true` and check the log file for any problems.

For more details, see issue #27853.

## Desirable Changes in Modules

You should look through changes in this section and see if they might apply to your module. If so, your module will be a better citizen of NetBeans 3.5 by making the recommended changes.

### Use `InstalledFileLocator`

If your module needs to search for a related file in the NetBeans installation, generally something packed into its NBM, prior to 3.5 there was no supported way of finding such a file. Now there is: `org.openide.modules.InstalledFileLocator` can find files installed alongside the module. Modules which searched undocumented system properties such as `netbeans.home` to find associated files should be changed to use the new service.

    File f = InstalledFileLocator.getDefault().locate(
        "docs/my-docs/index.html", "org.netbeans.modules.myself", true);
    if (f != null) {
        HtmlBrowser.URLDisplayer.getDefault().showURL(f.toURL());
    }

If you are looking for the module JAR itself, you may still prefer to use this idiom:

    File jar = new File(ThisModuleClass.class.getProtectionDomain().
                        getCodeSource().getLocation().getFile());

When using this new service, be sure to depend on it:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 3.21
    OpenIDE-Module-Requires: org.openide.modules.InstalledFileLocator

For more details, see issue #28683.

### Use `EditorCookie.Observable`

It was not possible to listen on changes in state of document before the NetBeans 3.5. Typical workaround was to cast object implementing `EditorCookie` to `CloneableEditorSupport` and use its state change listener. This however did not work in case when implementation of `EditorCookie` was based on `EditorSupport`.

The newly added `org.openide.cookies.EditorCookie.Observable` should eliminate this deficiency. It extends `org.openide.cookies.EditorCookie` and adds possibility to listen on changes of several document states:

- modified state of the document
- opened state of the document
- list of panes in which the document is opened

Recommended change for authors of editors is to implement directly `EditorCookie.Observable` instead of `EditorCookie` only. The `CloneableEditorSupport` (and also old deprecated `EditorSupport`) was extended to provide all necessary implementation.

Recommended change for clients which need to listen on document state changes and which were using `CloneableEditorSupport` till now is to replace the code and use `EditorCookie.Observable`. All NetBeans editors were modified to implement it and provide this cookie.

When using this new class, be sure to depend on correct version:

    OpenIDE-Module-IDE-Dependencies: IDE/1 > 3.40

For more details, see issue #31101.

# 3.3 -> 3.4 Upgrade Guide

This upgrade guide outlines notable API changes between NetBeans 3.3 and 3.4.

## Notable Incompatibilities

Check for changes here which might cause problems for your module if left uncorrected.

### XML MIME types

While not strictly speaking a compatibility issue, as it does not involve behavior specified by the Open APIs, developers whose modules operate on XML files should take note of a change in the NetBeans XML Core module from 3.3 to 3.4. Previously this module was configured to recognize all `*.xml` files (and a few other extensions) by default, as well as any file object marked with the MIME type `text/xml`.

In NetBeans 3.4, the module will also recognize `application/xml` and in fact any MIME type matching the pattern `*/*+xml`. Therefore, other modules which recognize certain subtypes of XML file might find the 3.4 data loader picking up the files instead. This is manifested by the files appearing with the generic XML icon:

To correct the problem, you should just need to ensure that your manifest explicitly asks for your loader to take priority:

    Name: my/module/MyDataLoader.class
    OpenIDE-Module-Class: Loader
    Install-Before: org.openide.loaders.XMLDataObject, org.netbeans.modules.xml.core.XMLDataObject

Even without changes to the module, end users can manually work around the problem if it occurs by reordering Object Types in the Options window to ensure that your object type appears above XML Files.

For more details, see issue #25163.

### Use of libraries from classpath

Previous versions of NetBeans permitted modules to freely use any libraries found in the startup classpath without declaring a dependency. This was dangerous, since the dependency declaration encapsulates information about what libraries the module uses. When a dependency fails, the failure can be presented politely to the user, rather than throwing a `NoClassDefFoundError` at runtime.

To enforce the rule, NetBeans 3.4 will refuse to serve certain classpath libraries to modules which do not declare a proper dependency. Additionally, the JavaHelp library was moved into a module in NetBeans 3.4; previously it was accessible on the classpath.

One benefit besides safety is that modules which do not declare dependencies on the classpath versions of these packages are free to use specific other versions simply by adding suitable JARs to their `Class-Path` manifest attribute.

In particular, here are the proper declarations you will need for each package:

Required Dependency Declarations in NetBeans 3.4
Package(s) | Dependency | Notes
`org.netbeans.core.**`, `org.netbeans.beaninfo.**` | `OpenIDE-Module-Module-Dependencies: org.netbeans.core/1` | Using any such packages is very dangerous and compatibility for your module in future releases is not assured.
`org.netbeans.lib.terminalemulator.*` | `OpenIDE-Module-Package-Dependencies: [org.netbeans.lib.terminalemulator.TermListener]` |
`org.apache.regexp.*` | `OpenIDE-Module-Package-Dependencies: [org.apache.regexp.RE]` | Use the Regexp autoload module or JDK 1.4's built-in regexps in NB 3.6.
`org.apache.crimson.subpackage.*` | `OpenIDE-Module-Package-Dependencies: org.apache.crimson.subpackage[SampleClass] > 1.1` | Declare the particular package(s) you are using, e.g. `org.apache.crimson.tree`. You are living dangerously if you depend on a particular XML parser.
`org.apache.xerces.**` | `OpenIDE-Module-Package-Dependencies: [org.apache.xerces.SampleClass]` | Again, using such a dependency is strongly discouraged. Consider using the Xerces parser autoload module instead. (Note: not available in NetBeans 3.4; added to the build for subsequent releases.)
`org.apache.xml.serialize.*` | `OpenIDE-Module-Package-Dependencies: [org.apache.xml.serialize.EncodingInfo]` | This is safer than depending on the Xerces parser proper, but it is still best to avoid such a dependency if possible. Consider using `XMLUtil.write(...)` instead, assuming you do not need two-way editing (preservation of whitespace).
`javax.help.**` | `OpenIDE-Module-Module-Dependencies: org.netbeans.modules.javahelp/1 > 1.0` | Note that this dependency will not be satisfiable in NetBeans 3.3. More information
`org.w3c.dom.**`, `org.xml.sax.**`, `javax.xml.**` | (no dependencies required) | These API classes are available to all modules automatically. There is no guarantee that implementations of full JAXP will be available, however; but you may request this: see JAXP information for more details.

For more details, see issue #19622.

## Desirable Changes in Modules

You should look through changes in this section and see if they might apply to your module. If so, your module will be a better citizen of NetBeans 3.4 by making the recommended changes.

### Declare public packages

As of NetBeans 3.4, it is possible to declare Java packages in your module which provide a public API (or SPI - Service Provider Interface) to other modules. By default, as in previous releases, all Java packages in your module are considered fair game to a module depending on your module, subject to Java access restrictions.

Now you can declare that only certain packages are to be considered part of the API of your module and accessible to others. Classes in other packages will be inaccessible outside your module, even if they are public. This declaration helps enforce separation of interface from implementation. Consult the Modules API for details; an example:

    OpenIDE-Module-Public-Packages: org.netbeans.api.myapi.*

Modules with an official, documented, maintained API are encouraged to use this new declaration to enforce it. Modules which intentionally have no API they wish to expose to other modules can also declare this:

    OpenIDE-Module-Public-Packages: -

See the Versioning Policy for suggested guidelines on providing an API from a module.

### Purify execution classpath

Previous versions of NetBeans tended to include too many items in the classpath used by user applications. Specifically, external compilation and execution would include in the classpath libraries used by NetBeans itself. This was convenient in a few cases but usually undesirable, sometimes a source of great confusion. In NetBeans 3.3, the default classpath for the external Java compiler was purified to include only the JRE's own libraries. In NetBeans 3.4, the change was completed by removing extraneous items from the classpath for the external Java executor.

However the Open APIs code did not change, and only the standard executor was changed. Modules may provide customized executors by subclassing `ProcessExecutor`, for example. They then typically construct a command parameter to include a `-classpath` argument. Executors defined by older modules may still include NetBeans' own startup and library paths, or even the JRE boot classpath, as derived from various methods in `NbClassPath`. For consistency with the new executor style, all these extraneous paths should be removed in the default executor configuration. What should remain:

1. The filesystems path, from `NbClassPath.createRepositoryPath(FileSystemCapability.EXECUTE)`. This can be configured by users simply by mounting or unmounting filesystems.

2. Optionally: a custom additional Classpath, by default blank, which will be appended to the filesystems path. While the user could just directly edit the External Process command template, it is more convenient to leave it untouched and use the custom property editor dialog for `NbClassPath`.

Compiler and debugger type classpaths should also be checked to ensure they are by default free of any libraries used by the NetBeans IDE.

If you have a library shipped as part of your module's NBM which can be used by user applications and which you feel is important to average users of your module, you may include it in the default classpaths used for execution, compilation, and debugging. Just create a declarative mount: see Move settings to layers: Specification filesystem instances for an explanation. Users may simply unmount this library if they are not interested in using it.

### Require a JavaHelp implementation

In NetBeans 3.3, the Modules API specified that you could install help sets conforming to the JavaHelp specification. In NetBeans 3.4, in the interests of greater modularity, JavaHelp is handled by an independent module. In order to ensure that this module is enabled when it is needed (it is an autoload), all modules with help sets should declare in their manifest:

    OpenIDE-Module-Requires: org.netbeans.api.javahelp.Help

For compatibility, older modules will automatically be considered to require JavaHelp. But newer modules (distinguished by requesting a post-2.2 specification version using `OpenIDE-Module-IDE-Dependencies`) must explicitly ask for JavaHelp support if they want it.

Any module referring directly to the JavaHelp Java-level APIs in `javax.help.*`, rather than simply installing a help set, must declare:

    OpenIDE-Module-Module-Dependencies: org.netbeans.modules.javahelp/1 > 1.0

This should be given in addition to or instead of the `OpenIDE-Module-Requires` above.

For more information, see issue #19620 and issue #27776.

### Move manifest nodes to layers

Even more types of module-provided settings can in 3.4 be registered via XML layer rather than in manifest. Layers are more flexible and brandable.

The basic definition of how settings in layers work is given in the Services API.

Here is list of types of nodes that might formerly have been present in a manifest which should be moved:

- Runtime nodes. Nodes of type `Environment` should be placed in the `UI/Runtime/` folder using the `*.instance` syntax, simply specifying the class of the node in question.

- Session nodes. Nodes of type `Session` should be placed in an appropriate subfolder of the `UI/Services/` folder, again using the `*.instance` syntax.

- Root nodes. Nodes of type `Root` should be placed in the `Windows/Components/` folder using `*.settings` syntax, using a `org.openide.explorer.ExplorerPanel` as the component. Use the ability of `*.settings` files to specify a static factory method to associate the explorer panel with your root node. Consult the Window System API: XML Layers for details. You may also want to add an action to the View menu which shows and focuses your Explorer tab if it is not already.

### `RequestProcessor` API changes

In NetBeans 3.3, performance and thread analysis revealed two problems with `RequestProcessor` usage. One was that the default `post(Runnable)` call forced serialization of requests, even when that was not the explicit intent, which often produced deadlocks between two requests. Another problem was that users of private `RequestProcessor` instances (a common way to avoid the abovementioned deadlocks) were inadvertently getting a dedicated thread each, which was a lot of overhead.

For NetBeans 3.4, newer calls make it easier to post tasks exactly how you want to post them, and still avoid unnecessary thread creation. The most common change module authors should do is to eliminate unnecessary serialization.

    // OLD WAY:
    public void somethingChanged(TheEvent ev) {
        RequestProcessor.postRequest(new Runnable() {
            public void run() {
                // Do this asynchronously, i.e. do not run in the listener callback.
                // But no one cares exactly when you do it, just soon.
                reactToTheChange();
            }
        });
    }
    // CAN OFTEN BE REPLACED BY:
    public void somethingChanged(TheEvent ev) {
        RequestProcessor.getDefault().post(new Runnable() {
            public void run() {
                // Will still be run asynchronously, but won't deadlock if
                // it happens to waitFinished() on some other RP task.
                reactToTheChange();
            }
        });
    }

For details on the various ways to start an asynchronous task and an explanation of when you would want to use one style over the other, see the `RequestProcessor` class Javadoc.

### Enable auto update of module without restart

There is new feature in the Auto Update client, allowing installation of many modules without restarting the IDE. This quick installation can be applied only to a module NBM which:

- is new (not present in the current installation)
- contains neither `netbeans/bin` nor `netbeans/lib` directories
- has the `needsrestart` attribute set to `false`. You can specify this attribute in the `makenbm` task of the module's build script.

If your module has no particular reason to require a restart of NetBeans before it can be used, you are encouraged to set this flag to `false`: the default is `true` for compatibility reasons.

### Add a description for the selected node in the Explorer

Each node should have a description to characterize the node's purpose and use in the IDE for the end user. This description is shown in the "mini status bar" in the Explorer panel in the IDE. Each module should add a description for each type of node it provides.

There are two ways to make such a description appear.

1. (Preferred) If a node has a short description (`Node.getShortDescription()`) then this is used in the mini status bar as well as in the node's tool tip. So for most nodes, you can just override `getShortDescription()` to return the desired localized text. If the node already had a tool tip and it is acceptable, no change is needed.

2. Sometimes a node will already have a short description used in the tooltip, but it is not appropriate for the mini status bar. Or no tool tip is desired at all. In such cases it is possible to provide a distinct status bar message. Just use the `nodeDescription` attribute:

       public MyNode() {
           super(Children.LEAF);
           setValue("nodeDescription",
                    NbBundle.getMessage(MyNode.class, "DESC_MyNode"));
       }

For a quick summary of which nodes are still missing descriptions, run NetBeans with the command-line switch `-J-Dnetbeans.log.node.description=true`, exercise relevant features of the IDE, and watch the log file.

More information can be found in issue #9940.

### JAR Packager - registration of `ArchiveBuilder`s, extended properties moved to layer

Relevant to modules which programmatically extend the capabilities of the JAR Packager. For details see issue #21323.

### Change in format of `DataShadow`s

Before 3.4 the only way to create `DataShadow`s (symbolic links) was to create a file with the extension `.shadow` containing two lines of text. The first line contains the name of the linked-to file. The second line contains the (system) name of the filesystem in which the linked-to file resides. If the second line is omitted all filesystems are searched for the linked file.

For 3.4 a new preferred format was introduced. The `*.shadow` file is allowed to be empty (byte length zero). If so then the `FileObject` should have the attribute `originalFile` and optionally also `originalFileSystem`, both of value type `String`. The second attribute may be omitted if the filesystem on which the `*.shadow` file resides is to be searched for the linked file, which is the commonest case.

The change was designed primarily for XML layers forming the system filesystem. It is no longer necessary to use a CDATA section for the shadow contents, which is a bit cleaner to write and more memory-efficient.

The old style:

    <folder name="FooFolder">
                <file name="the.shadow">
                    <![CDATA[BarFolder/original.file
    SystemFileSystem
    ]]>
                </file>
            </folder>

The new preferred style:

    <folder name="FooFolder">
        <file name="the.shadow">
            <attr name="originalFile" stringvalue="BarFolder/original.file"/>
            <!-- optional: -->
            <attr name="originalFileSystem" stringvalue="SystemFileSystem"/>
        </file>
    </folder>

### Eager modules

NetBeans 3.3 introduced autoload modules which are suitable for situations where the module provides no inherent functionality but is just used as a library for the benefit of other modules. In NetBeans 3.4 you may also have eager modules, or "bridges". These modules cannot be turned off by the user, unless they depend on normal modules which are turned off. This is appropriate for small modules which simply provide bridging functionality between two or more major modules.

For example, `i18n-form.jar` is turned on only when `i18n.jar` and `form.jar` are both turned on; it lets the I18N support understand how to work with Form Editor files and guard blocks. The user might want to disable I18N support, or might want to disable GUI form support, but if both of these are enabled then they are expected to cooperate. The existence of a separate module to bridge them is only an implementation detail: it permits the two major modules to be enabled independently of one another, by separating out the dependency. Therefore it is made eager.

You can easily make a module eager. Just place it in the `modules/eager/` folder rather than `modules/`.

### Use new open/close/show/hide methods for `TopComponent`

There are several new protected notification methods in `TopComponent`:

- `componentOpened`
- `componentClosed`
- `componentShowing`
- `componentHidden`

When added to the existing `componentActivated` and `componentDeactivated` methods, this means that if you have a custom component, you can more precisely control its resource management than before.

For example, your component might need to perform heavyweight initialization when it is displayed - opening files, parsing them, and so on. In NetBeans 3.3, if your component was open but in not showing in a multitab container after a restart of NetBeans, it would need to perform all this work when the window system was opened - even though the user was not actually looking at your component at all. Now you can override `componentShowing` to perform this initialization on demand. If the tab is not selected by the user, or not selected for a while, the initialization can be deferred, improving startup time and perhaps reducing memory use.

### Provide final children list for a node

Children of a node are often initialized completely when `Children.addNotify` is called. But for some cases, the creation of children can be time-consuming or use critical threads, and so it is done asynchronously. For example, objects inside a folder are recognized soon after the folder is expanded, but not synchronously, in case the folder is very large. As another example, Java sources show a Please wait... node until they are parsed.

While desirable in the Explorer GUI, such behavior can be troublesome for other purposes. Scripting and automated testing are made much more complicated if the proper subnodes are not available at once. `MenuView` (used for some popup menus) also suffered from Swing display problems associated with dynamic changes to menu contents.

So for NetBeans 3.4, there is a new method `Children.getNodes(true)` which you may override. By default it behaves identically to `Children.getNodes()`. However, if your node adds subnodes after a delay, you are strongly encouraged to override it. The implementation ought to block, perform whatever calculations it needs, and provide a complete and finalized children list before returning. (The children may still be changed later in response to various events, of course.)

### Supply `TemplateWizard.Iterator` as a cookie

In NetBeans 3.3, custom template wizard iterators (panel sequences for the New wizard) had to be declared using the file attribute `templateWizardIterator` on the template's primary file. This was generally written into the layer. There were several problems with this when used for wizards applicable generally to any template of a given object type, such as the several panels used on Java classes:

- There were excess file attributes in layers for modules with many templates.

- Users who created their own templates did not get the wizard, unless messy hacks were implemented.

- Other modules making templates of the same object type needed to know the exact class name of the wizard, which is potentially fragile.

For NetBeans 3.4, you may instead supply `TemplateWizard.Iterator` as a cookie from a `DataObject` subclass you create. Then the wizard will by default be available to all templates of that type. No file attribute is needed.

Use of the file attribute is still appropriate for cases where the wizard iterator is only applicable to a certain special template designed to launch that wizard, and not to all templates of that data object type. You can also override the cookie with the file attribute if you need a special wizard for just a few templates.

### Map file objects to URLs

Before NetBeans 3.4, it was hard to find a good URL corresponding to a given `FileObject`. `nbfs:` protocol was available for all file objects, but this protocol is useless outside NetBeans (e.g. for displaying to an external web browser). `file:` and `jar:` URLs could be constructed for some file objects manually, but not very reliably.

In 3.4, the new class `org.openide.filesystems.URLMapper` may be used to declare helpful URL equivalents for file objects. For example, an HTTP-based filesystem could register a mapper producing `http:` URLs for its files. You can use static methods to find the best URL for a given file object.

Code which constructed URLs in an ad-hoc manner should be upgraded to use the new utility methods. Implementors of custom `FileSystem`s are encouraged to supply mappers meaningful to files residing in filesystems of that type.

### Adjust New wizard template folder order

The folders in the New wizard were rearranged for NetBeans 3.4 in various ways. If you supply your own template folder beneath `Templates/` in your layer, check the resulting order in NetBeans 3.4 and adjust it to look better if necessary.

### Stop using FileSystemCapabilities

The next major version of NetBeans will ruin the assumption that roots of classpath are in filesystem roots; roots of classpath will be defined explicitly by settings. To ease migration a new ClassPath API was introduced in NetBeans 3.4, which we commited to make work even with the new project infrastructure.

If you are using `FileSystemCapabilities.{COMPILE|DEBUG|EXECUTE}` to search for resources, or to produce FileObjects you can construct classpath information from, you should consider using corresponding calls to ClassPath API. The old approach still works in NetBeans 3.4 and 3.5, but will break in NetBeans 4.0. See ClassPath API documentation online for more information.

# 3.2 -> 3.3 Upgrade Guide

This upgrade guide outlines notable API changes between NetBeans 3.2 and 3.3.

## Notable Incompatibilities

There is only one incompatibility which is likely to be relevant.

`MultiDataObject.cookieSet` (getter and setter) are now protected rather than public, affecting compilability of sources (though binary compatibility is retained). See the change summary for the rationale for this change and suggested workarounds.

A similar change was also made to `AbstractNode.cookieSet` which is likely to have a smaller impact.

## Desirable Changes in Modules

This section lists changes desired when upgrading to 3.3 from 3.2, in addition to older changes.

### Move settings to layers

Many types of module-provided settings can in 3.3 be registered via XML layer rather than in manifest. Besides permitting greater flexibility, there are performance benefits to doing this.

The basic definition of how settings in layers work is given in the Services API.

Here are the things that might formerly have been present in a manifest which should be moved:

- System options. They may be placed in the `Services/` folder using `*.settings` syntax, with a link from an appropriate category of `UI/Services/`. Provide a localized name and icon for the settings file (not its link).

- Services. Register as settings in an appropriate `Services/` subfolder (conventionally `Executor/`, `CompilerType/`, `DebuggerType/`, `SearchType/`, `IndentEngine/`, etc.). Additionally, if the service has any user-configurable properties such that it would make sense to create more than one instance, add an identical settings file into the matching subdirectory of `Templates/Services/`. Provide a localized name and icon for the settings file(s). Relative order of services (e.g. priority for choosing a default) may be accomplished using folder ordering.

  Currently registered services should normally be marked with the file attribute `SystemFileSystem.layer` set to `project`, making them project-specific. This is not yet an official API, just a hint recognized for the 3.3 release. The same hint may be applied to other settings, such as certain system options.

- Filesystem types. Register as a setting in `Templates/Mount/`, generally with a localized name and icon as well as optionally a template iterator and description.

- Specific filesystem instances. Filesystems to be initially mounted by the module can also be registered by including settings in `Mount/` rather than via procedural mounting. You can either use `*.settings` syntax if you intend for the mount to be user-configurable, or for the common case that you are trying to mount a Java library ZIP/JAR intended for the user classpath which is present in the IDE installation, or a Javadoc ZIP/JAR/folder for the Javadoc tab which is also present in the IDE installation, you can create XML files using DTDs supported by modules. See the Filesystems API for details.

  Warning: when doing this you should consider compatibility of old user settings. Typically in pre-3.3 releases, mounts (including those made programmatically from module installers) would have been stored serialized into project settings; you must be prepared to handle their deserialization. Assuming the new file under `Mount/` (or a subdirectory) handles the mounting needs and obsoletes the former serialized setting, you can cause the old mount to disappear after a restart cycle, as in `org.apache.tools.ant.module.AntModule`. Do not try to return `null` from `writeReplace` as it will not work (see #17476 for details).

- Debuggers can probably be registered via lookup in `Services/`. (Untested; only one is active at a time anyway. Debugger types are services, q.v.)

- Clipboard convertors. If anyone actually uses these, they should be registered via lookup in `Services/`.

- JavaHelp - see below.

- Module installers - many tasks formerly done procedurally can now be done in layers; covered throughout this document, and also see below. Many installers can be deleted outright; every installer which currently overrides `readExternal` and `writeExternal` should be changed if at all possible to not keep any serialized state. (It is safe to delete these methods or the entire installer if you no longer keep any state. The IDE will not attempt to call the default implementations at all if these methods are not overridden, so you do not need to override `readExternal` just to keep compatibility.)

For most of these cases (especially system options, services, filesystems, and JavaHelp) there are copious examples to be found in the layers of standard NetBeans modules in development sources. Do not forget to also look at the localizing bundles referred to by the layers, and the settings files themselves which are normally linked to with the `url="..."` attribute of `<file>` for performance reasons (inline file contents are a bit slower to parse). For example, `ant/src/org/apache/tools/ant/module/resources/AntModuleLayer.xml` has these relevant entries:

    <!-- Not the complete layer, just interesting pieces: -->
    <folder name="Services">
        <!-- Register two compiler types and an executor into the default service pool. -->
        <folder name="CompilerType">
            <!-- See ant/src/org/apache/tools/ant/module/resources/AntCompiler.settings for contents. -->
            <file name="org-apache-tools-ant-module-AntCompiler.settings" url="AntCompiler.settings">
                <!-- Make any changes specific to the project. -->
                <attr name="SystemFileSystem.layer" stringvalue="project"/>
                <!-- Give it a nice display name; otherwise the service has to be actually loaded in order -->
                <!-- to display its icon. See ant/src/org/apache/tools/ant/module/run/Bundle.properties. -->
                <!-- The key will be named "Services/CompilerType/org-apache-tools-ant-module-AntCompiler.settings". -->
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                <!-- Give it a nice icon, as above. -->
                <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
            </file>
            <file name="org-apache-tools-ant-module-IndirectAntCompiler.settings" url="IndirectAntCompiler.settings">
                <attr name="SystemFileSystem.layer" stringvalue="project"/>
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
            </file>
        </folder>
        <folder name="Executor">
            <file name="org-apache-tools-ant-module-AntExecutor.settings" url="AntExecutor.settings">
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
                <attr name="SystemFileSystem.layer" stringvalue="project"/>
            </file>
        </folder>
        <!-- A system option. -->
        <file name="org-apache-tools-ant-module-AntSettings.settings" url="AntSettings.settings">
            <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.Bundle"/>
            <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
        </file>
    </folder>
    <folder name="Templates">
        <folder name="Services">
            <!-- Make it possible for the user to create new services too. -->
            <folder name="CompilerType">
                <!-- Use the same initial settings as for the default instance in the pool. -->
                <file name="org-apache-tools-ant-module-AntCompiler.settings" url="AntCompiler.settings">
                    <!-- They have to be marked as templates, or they will not be included in the wizard. -->
                    <attr boolvalue="true" name="template"/>
                    <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                    <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
                </file>
                <file name="org-apache-tools-ant-module-IndirectAntCompiler.settings" url="IndirectAntCompiler.settings">
                    <attr boolvalue="true" name="template"/>
                    <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                    <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
                </file>
            </folder>
            <folder name="Executor">
                <file name="org-apache-tools-ant-module-AntExecutor.settings" url="AntExecutor.settings">
                    <attr boolvalue="true" name="template"/>
                    <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.run.Bundle"/>
                    <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
                </file>
            </folder>
        </folder>
    </folder>
    <folder name="UI">
        <folder name="Services">
            <!-- Display the system option under the "Building" category in Options. -->
            <folder name="Building">
                <!-- Point to the real settings file (always on the system filesystem). -->
                <file name="org-apache-tools-ant-module-AntSettings.shadow">
                    <![CDATA[Services/org-apache-tools-ant-module-AntSettings.settings
    SystemFileSystem
    ]]>
                </file>
            </folder>
        </folder>
    </folder>
    <folder name="Mount">
        <!-- Add a Javadoc default mount. The user can unmount it but not customize it. -->
        <folder name="Javadoc">
            <!-- The file name does not matter but should be unique. -->
            <file name="org-apache-tools-ant-module-javadoc.xml">
                <!-- The contents could also be given in a separate file. -->
                <![CDATA[<?xml version="1.0"?>
    <!-- The DOCTYPE's public ID is mandatory for the document to be processed. -->
    <!DOCTYPE Javadoc PUBLIC
              "-//NetBeans IDE//DTD JavadocLibrary//EN"
              "http://www.netbeans.org/dtds/JavadocLibrary-1_0.dtd">
    <Javadoc>
      <!-- This is a path inside the NetBeans installation directory. -->
      <!-- See the ant/release/ folder in sources. -->
      <Archive name="docs/ant-api.zip"/>
    </Javadoc>
    ]]>
                <!-- Nice name and icon to show in Filesystems Settings. -->
                <attr name="SystemFileSystem.localizingBundle" stringvalue="org.apache.tools.ant.module.resources.Bundle"/>
                <attr name="SystemFileSystem.icon" urlvalue="nbresloc:/org/apache/tools/ant/module/resources/AntIcon.gif"/>
            </file>
        </folder>
    </folder>

The following cannot be moved from a layer:

- Action sections. "Tools" actions cannot yet be registered via layer.
- Data loaders. Due to possible feedback loops and other complications, loaders must still be registered in a manifest.
- Nodes (all three types of global node installation). Layer installation not yet implemented.

### Define workspaces and windows in layers

If your module for 3.2 defined its own workspaces or modes, or otherwise performed some sort of setup of the window system from the module installer, it should be converted in 3.3 to define these things using an XML layer. There are several benefits to doing so:

- Better performance - avoid running code during startup. Objects are initialized only as the window system needs them.

- Simplification of code - rather than procedurally checking for window system objects and creating them and removing them at uninstallation, more is done declaratively in XML.

- More power - you can control MDI frame attachment modes and such advanced features not available through the Java-level API. Modules can also cooperate to incrementally supply pieces of a workspace, and so on.

- Better uninstallation and project switching - your layer-supplied workspaces, modes, and components will be uninstalled more cleanly with your module, and will serve as a default for all projects (but customizable in each) without added effort.

There is a migration guide available to help you convert old procedural code to the new XML style. Full details of the XML format and behavior are given in the Window System API.

### Avoid persisting closed `TopComponent`s

Before NetBeans 3.3, it was normal for all top components to be persistent in the user's project, even closed ones. This was not always desirable since some components cannot be properly serialized; and others can but there is no need to store them all the time, they just add clutter to user settings. In the new window system, modules have an option to disable persistence of their top components after project switch or IDE shutdown. (The default is still to persist all components, for compatibility.)

If your top component either cannot be properly serialized and deserialized because it includes critical transient information, or for UI reasons it is undesirable to ever keep it open after a switch in the window system, you can add a Swing client property to it giving the window system this hint:

    putClientProperty("PersistenceType", "Never"); // NOI18N

If you wish for it to be saved when it is open (at the time of project switch or IDE shutdown) but no information about it should be kept after it is closed, use:

    putClientProperty("PersistenceType", "OnlyOpened"); // NOI18N

For efficiency during IDE or project open and in the interests of avoiding clutter in the user directory, it is recommended that most top components use one of these hints (normally `OnlyOpened`).

Warning: this is only a hint which may not be respected in future releases; so for safety `TopComponent`s which cannot be safely deserialized at all should still `writeReplace` to `null`, so as to avoid problems in a future release.

### Localize manifests with bundles

In 3.2, all metainformation about a module such as its display name needed to be kept in its manifest. There was a facility for localizing human-visible strings, using variants on attribute keys; unfortunately the JRE does not current support non-ASCII characters in manifests, so this was not very useful. For 3.3, all localizable strings formerly in manifests ought to be moved to resource bundles, where they can be properly localized. This feature is turned on by a new manifest attribute pointing to the bundle.

There is an existing document describing how to do this conversion: Manifest Localization Guide

### Install JavaHelp help sets with layers

Before 3.3, there was only one way to add JavaHelp documentation for a module, using the Modules API. You included a helpset in the module and then used the `OpenIDE-Module-Description` attribute to refer to it. For NetBeans 3.3 JavaHelp functionality can be registered via layer instead of manifest, with several advantages:

- Performance during startup - while some effort is made to improve performance over 3.2 even for manifest-installed helpsets, they still need to be parsed in order to retrieve helpset title and home ID. Using a layer, this information is specified explicitly and the IDE need do nothing until the helpset is actually displayed.

- Flexibility - using the layer syntax, you can explicitly control whether helpsets are merged into the master helpset or not, and if so in which order; control whether links are made in the Help | Help Sets submenu, and if so in which order, and how the link appears; add additional convenience links with the same helpset; and more.

To use this new system effectively, first remove the obsolete manifest declaration. Now in your layer you need to add three items:

1. An instance to the help set itself, conventionally done with a special DTD used for this purpose and underneath `Services/JavaHelp/`. This registers the existence of the help set, and controls its merging into the master help set.

2. A shortcut to the help set (typically to its home ID), conventionally using another special DTD and placed under `Menu/Help/HelpShortcuts/`. This registers the menu item including its name and icon, and controls ordering.

3. The same shortcut in the actions pool, conventionally under `Actions/Help/`, permitting users to copy the help set reference elsewhere and safely customize their shortcuts menu knowing it will still be available here.

Here is an excerpt from the API Support module's layer demonstrating these things. Note that the `usersguide` module (Online Help) provides a few marker files in its layers which help sort other help sets and menu items into the "general zone": the IDE's main Online Help itself comes first, then a separator (in the menu), then module help sets (or menu items), then another separator, then module help sets (or menu items) which represent "third-party" or bundled documentation (such as the Ant User Manual included in the Ant support module).

    <filesystem>
        <folder name="Services">
            <!-- Register the HelpSet in lookup: -->
            <folder name="JavaHelp">
                <!-- Merge it after the main online help: -->
                <attr name="org-netbeans-modules-usersguide-above-regular.txt/org-netbeans-modules-apisupport-helpset.xml"
                      boolvalue="true"/>
                <!-- This DTD gives an instance of HelpSet: -->
                <file name="org-netbeans-modules-apisupport-helpset.xml">
                    <![CDATA[<?xml version="1.0"?>
    <!DOCTYPE helpsetref PUBLIC
              "-//NetBeans//DTD JavaHelp Help Set Reference 1.0//EN"
              "http://www.netbeans.org/dtds/helpsetref-1_0.dtd">
    <!-- By default it is set to merge. nbdocs: looks in the module JAR(s) and docs/ folder. -->
    <helpsetref url="nbdocs:/org/netbeans/modules/apisupport/help/HelpSet.hs"/>
    ]]>
                </file>
                <!-- And merge before additional helpsets such as the Ant Manual: -->
                <attr name="org-netbeans-modules-apisupport-helpset.xml/org-netbeans-modules-usersguide-below-regular.txt"
                      boolvalue="true"/>
            </folder>
        </folder>
        <folder name="Menu">
            <folder name="Help">
                <!-- Add a menu item in Help | Help Sets: -->
                <folder name="HelpShortcuts">
                    <!-- Again some ordering: -->
                    <attr name="org-netbeans-modules-usersguide-sep.instance/org-netbeans-modules-apisupport-mainpage.xml"
                          boolvalue="true"/>
                    <!-- Instance of a menu item: -->
                    <file name="org-netbeans-modules-apisupport-mainpage.xml">
                        <![CDATA[<?xml version="1.0"?>
    <!DOCTYPE helpctx PUBLIC
              "-//NetBeans//DTD Help Context 1.0//EN"
              "http://www.netbeans.org/dtds/helpcontext-1_0.dtd">
    <!-- Give the help ID to open. By default shows master help set, you can instead -->
    <!-- show just this help set if you prefer: -->
    <helpctx id="org.netbeans.modules.apisupport.HOMEID"/>
    ]]>
                        <!-- Make it appear with a nice name and icon. -->
                        <attr name="SystemFileSystem.localizingBundle"
                              stringvalue="org.netbeans.modules.apisupport.resources.TemplateNames"/>
                        <attr name="SystemFileSystem.icon"
                              urlvalue="nbresloc:/org/netbeans/modules/apisupport/resources/ShowAPIJavadocIcon.gif"/>
                    </file>
                    <attr name="org-netbeans-modules-apisupport-mainpage.xml/org-netbeans-modules-usersguide-lower-sep.instance"
                          boolvalue="true"/>
                </folder>
            </folder>
        </folder>
        <folder name="Actions">
            <!-- Add to actions pool too: -->
            <folder name="Help">
                <!-- No need for any special ordering here. -->
                <file name="org-netbeans-modules-apisupport-mainpage.xml">
                    <![CDATA[<?xml version="1.0"?>
    <!DOCTYPE helpctx PUBLIC
              "-//NetBeans//DTD Help Context 1.0//EN"
              "http://www.netbeans.org/dtds/helpcontext-1_0.dtd">
    <helpctx id="org.netbeans.modules.apisupport.HOMEID"/>
    ]]>
                    <attr name="SystemFileSystem.localizingBundle"
                          stringvalue="org.netbeans.modules.apisupport.resources.TemplateNames"/>
                    <attr name="SystemFileSystem.icon"
                          urlvalue="nbresloc:/org/netbeans/modules/apisupport/resources/ShowAPIJavadocIcon.gif"/>
                </file>
            </folder>
        </folder>
    </filesystem>

(In your module it would be better to use `url="..."` to include these XML files separately rather than inline, which is a little faster.)

Do not forget also that the localized filenames need bundle entries, here from `apisupport/src/org/netbeans/modules/apisupport/resources/TemplateNames.properties`:

    Menu/Help/HelpShortcuts/org-netbeans-modules-apisupport-mainpage.xml=OpenAPIs Support
    Actions/Help/org-netbeans-modules-apisupport-mainpage.xml=OpenAPIs Support

The helpset itself must be accessible with the `nbdocs` protocol. While it still works to copy helpsets unpacked to the `docs/` directory of the IDE installation, this practice is discouraged. In most cases using a JavaHelp helpset off-line is not important to users anyway. The proper thing to do is to keep the helpset available from the module classloader, i.e. its JAR, or more cleanly in an extension JAR (or ZIP). Conventionally these go in the `modules/docs/` directory. So for example include this in your module manifest:

    Class-Path: docs/apisupport-manual.jar

where `modules/docs/apisupport-manual.jar` contains the complete helpset, starting from the resource `org/netbeans/modules/apisupport/help/HelpSet.hs`. In such a case you can use the `nbresloc` rather than `nbdocs` protocol in the helpset registration URL.

Details of JavaHelp installation are given in the JavaHelp Integration API.

### Ability to turn modules on and off, list all modules

In NetBeans 3.2 there was no API-level access to the set of installed modules nor any control over them. In 3.3 there is limited information and control available. Specifically you can:

- obtain a list of all known modules

- determine if a module is enabled or not, and listen to this change

- programmatically enable or disable a known module

- for your own module, refuse to be installable if some criteria (such as presence of a license file or external application) are not met

For purposes of upgrading existing functionality, the last point is the most significant: if in NetBeans 3.2 your module attempted to manually turn off pieces of its GUI upon finding that some critical thing it needed was missing, for 3.3 this check should be done in `ModuleInstall.validate()`.

See the Modules API - Installers for information on using `validate`, and the Modules API - List of modules for information on the other new features.

### Use annotations to control GUI of editor

As of NetBeans 3.3 there is a new API which permits any module to interact with the GUI of the editor, specifically by making marks called annotations in the margin of the editor, highlighting complete lines or fragments of text, displaying tool tips and actions, and several other abilities. This is documented in the Editor API.

If in NetBeans 3.2 you are using the now-deprecated method `Line.markError` or one of several similar calls to indicate erroneous places in a document, you should for 3.3 create an annotation representing your error and attach it to the line instead. This is much more flexible. A sample implementation of an error annotation including how to attach and detach it at the proper times can be found in `ant/src/org/apache/tools/ant/module/run/OutputWriterOutputStream.java`. An excerpt from this class showing the essential code follows:

    /** This is called when a complete line of process output is collected.
     * It either prints it plain, or prints it with a hyperlink which when
     * clicked opens the offending source and attaches an error annotation.
     * 'writer' is an OutputWriter from a tab in the Output Window.
     */
    private void flushLine(String l) throws IOException {
        // ...
        Hyperlink link = /* create one based on erroneous line, or null */;
        if(link != null) {
            writer.println(link.getMessage(), link);
        } else {
            writer.println(l);
        }
    }

    /** Call this from ModuleInstall.uninstalled() to clean up. */
    public static void detachAllAnnotations() {
        synchronized (hyperlinks) {
            Iterator it = hyperlinks.iterator();
            while (it.hasNext()) {
                ((Hyperlink)it.next()).destroy();
            }
        }
    }
    private static final Set hyperlinks = new WeakSet(); // Set<Hyperlink>

    /** This is the annotation itself, which also knows how to behave in the
     * Output Window, and when to attach and detach itself.
     */
    private static final class Hyperlink extends Annotation implements OutputListener, PropertyChangeListener {
        private FileObject file; // file to jump to
        private int line1, col1, line2, col2; // line/col number to jump to, 0-based, -1 for unspecified
        private String message; // message it is saying, or null
        private boolean dead = false; // whether it has been destroyed
        /** Create it based on some parsing of the erroneous line, etc. */
        Hyperlink(FileObject file, int line1, int col1, int line2, int col2, String message) {
            this.file = file;
            this.line1 = line1;
            this.col1 = col1;
            this.line2 = line2;
            this.col2 = col2;
            this.message = message;
            synchronized (hyperlinks) {
                hyperlinks.add(this);
            }
        }
        /** See detachAllAnnotations() above. */
        void destroy() {
            doDetach();
            dead = true;
        }
        /** Get a message suitable for printing in the Output Window, based on error, line #, etc. */
        public String getMessage() { /* ... */ }
        // OutputListener methods:
        public void outputLineAction(OutputEvent ev) {
            if (dead) return;
            if (! file.isValid()) {
                Toolkit.getDefaultToolkit().beep();
                return;
            }
            if (message != null) {
                TopManager.getDefault().setStatusText(message);
            }
            try {
                DataObject dob = DataObject.find(file);
                EditorCookie ed = (EditorCookie) dob.getCookie(EditorCookie.class);
                if (ed != null) {
                    if (line1 == -1) {
                        // OK, just open it.
                        ed.open();
                    } else {
                        // Open the document, add the annotation, jump to the right line.
                        ed.openDocument();
                        Line l = ed.getLineSet().getOriginal(line1);
                        if (! l.isDeleted()) {
                            attachAsNeeded(l);
                            if (col1 == -1) {
                                l.show(Line.SHOW_GOTO);
                            } else {
                                l.show(Line.SHOW_GOTO, col1);
                            }
                        }
                    }
                } else {
                    Toolkit.getDefaultToolkit().beep();
                }
            } catch (DataObjectNotFoundException donfe) {
                TopManager.getDefault().getErrorManager().notify(ErrorManager.WARNING, donfe);
            } catch (IndexOutOfBoundsException iobe) {
                TopManager.getDefault().getErrorManager().notify(ErrorManager.WARNING, iobe);
            } catch (IOException ioe) {
                TopManager.getDefault().getErrorManager().notify(ErrorManager.WARNING, ioe);
            }
        }
        public void outputLineSelected(OutputEvent ev) {
            // Similar to the above but less aggressive. Do not forcibly open the document.
            if (dead) return;
            if (! file.isValid()) {
                return;
            }
            try {
                DataObject dob = DataObject.find(file);
                EditorCookie ed = (EditorCookie) dob.getCookie(EditorCookie.class);
                if (ed != null) {
                    if (ed.getDocument() == null) {
                        // The document is not opened, don't bother with it.
                        return;
                    }
                    if (line1 != -1) {
                        Line l = ed.getLineSet().getOriginal(line1);
                        if (! l.isDeleted()) {
                            attachAsNeeded(l);
                            if (col1 == -1) {
                                l.show(Line.SHOW_TRY_SHOW);
                            } else {
                                l.show(Line.SHOW_TRY_SHOW, col1);
                            }
                        }
                    }
                }
            } catch (DataObjectNotFoundException donfe) {
                TopManager.getDefault().getErrorManager().notify(ErrorManager.WARNING, donfe);
            } catch (IndexOutOfBoundsException iobe) {
                TopManager.getDefault().getErrorManager().notify(ErrorManager.WARNING, iobe);
            }
        }
        public void outputLineCleared(OutputEvent ev) {
            doDetach();
        }
        /** Attach myself to a line if this has not been done already. */
        private synchronized void attachAsNeeded(Line l) {
            if (getAttachedAnnotatable() == null) {
                Annotatable ann;
                // Text of the line, incl. trailing newline.
                String text = l.getText();
                if (text != null && (line2 == -1 || line1 == line2) && col1 != -1) {
                    // fits on one line
                    if (col2 != -1 && col2 >= col1 && col2 < text.length()) {
                        // one section of the line was specified
                        ann = l.createPart(col1, col2 - col1 + 1);
                    } else if (col1 < text.length()) {
                        // some column until end of line
                        ann = l.createPart(col1, text.length() - col1);
                    } else {
                        // some problem
                        ann = l;
                    }
                } else {
                    // multiple lines, something wrong with line, or no column given
                    ann = l;
                }
                // actually display the glyph etc.:
                attach(ann);
                // see if this line/fragment is changed or deleted in the future:
                ann.addPropertyChangeListener(this);
            }
        }
        /** Detach from the associated line, if necessary. */
        private synchronized void doDetach() {
            Annotatable ann = getAttachedAnnotatable();
            if (ann != null) {
                ann.removePropertyChangeListener(this);
                detach();
            }
        }
        // PropertyChangeListener method:
        public void propertyChange(PropertyChangeEvent ev) {
            if (dead) return;
            String prop = ev.getPropertyName();
            if (prop == null ||
                    prop.equals(Annotatable.PROP_TEXT) ||
                    prop.equals(Annotatable.PROP_DELETED)) {
                // Affected line has changed.
                // Assume user has edited & corrected the error.
                doDetach();
            }
        }
        // Annotation:
        public String getAnnotationType() {
            // Unique ID of this kind of annotation:
            return "org-apache-tools-ant-module-error"; // NOI18N
        }
        public String getShortDescription() {
            // This will become the annotation's tool tip text
            return message;
        }
    }

The annotation type is registered in the layer:

    <filesystem>
        <folder name="Editors">
            <folder name="AnnotationTypes">
                <file name="org-apache-tools-ant-module-error.xml"
                      url="error-annotation.xml"/>
            </folder>
        </folder>
    </filesystem>

and the actual definition mainly gives some GUI properties of the glyph:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE type PUBLIC
              "-//NetBeans//DTD annotation type 1.0//EN"
              "http://www.netbeans.org/dtds/annotation-type-1_0.dtd">
    <type name="org-apache-tools-ant-module-error"
          description_key="LBL_error_annotation"
          localizing_bundle="org.apache.tools.ant.module.resources.Bundle"
          visible="true"
          glyph="nbresloc:/org/apache/tools/ant/module/resources/error-glyph.gif"
          highlight="#FF8080"
          type="linepart"
    />

Also see issue #15920 for a suggestion on simplifying this whole process.

### Define file types using MIME resolvers

The MIME resolver facility is actually present in NetBeans 3.2 though it was essentially unused at the time. It provides a way for modules to register knowledge of what the MIME type of a file is. You can add a `MIMEResolver` implementation to lookup and filesystems will ask it for information of file object MIME type; typically it might scan initial bytes of a file for magic headers and so on. The system can cache the opening bytes of the file, making this reasonably efficient.

For the first time in NetBeans 3.3 it is possible to add a MIME resolver without any coding: a new XML format is defined which makes the most common tasks (decision trees) available. For example, you can ask that all XML files with a certain DTD be given a special MIME type. Or that all files beginning with a certain "magic" byte sequence be recognized as some MIME type.

How are these MIME types supposed to be used? There are a few different ways in which it can be helpful to directly associate proper MIME types to file objects, but the major reason to use them is to make `DataLoader`s simpler. If a MIME resolver, especially an XML one, can fully define what your file type is, then you may simply use a `UniFileLoader` with one item in its extension list - that MIME type. There are potential performance benefits here because the system can pool resolvers and apply them in batch.

Which modules should look at these? Ultimately probably all loaders should work this way. For the shorter term, consider switching complex data loader recognition logic to simplified loader logic paired with MIME recognition if you:

1. Recognize XML files by DTD, root element, or other common mechanism. Adding a new MIME resolver will make your module add very little overhead to the XML recognition process; keeping custom parsing tricks in the data loader adds a significant amount of overhead and prevents back-end optimizations by the IDE. Additionally your code will be much simpler.

2. Recognize any kind of file based on its contents, especially some distinctive marker in its header. Opening the file from a data loader is a significant source of overhead; the resolver pool caches these headers. Your code will also be simpler here if you can use a declarative resolver.

3. Need to have a MIME type associated with the actual `FileObject` anyway. For example, if it should be given some type when served from the internal web server.

The system of MIME resolution using declarative resolvers is documented in the Filesystems API. An example can be found in the Ant module (recognizing XML files based on root element). Consult the layer and data loader.

### Lazy instances with `InstanceCookie.Of`

If you were registering any kind of instance to lookup in NetBeans 3.2, or are considering doing it for the first time in NetBeans 3.3, make sure you understand how to prevent eager classloading from happening. Essentially: if you have some service implementation which you wish to register, and it is not actually used in the course of an IDE session, its class should never be loaded (the interface class probably will be).

This is done technically using `InstanceCookie.Of`, if you are providing the raw cookie. When using standard means of providing instances, there are matching ways to ensure you split the interface and implementation classes clearly enough to be lazy: the `instanceOf` attribute on `*.instance` files, and the `<instanceof/>` element in XML settings. See the Services API for more information.

### Enhanced lookup facilities supersede service types

There are many new features in the lookup system for 3.3. It would not be helpful to enumerate all of them because if you were not using lookup extensively in 3.2, you probably do not need to do much for 3.3 (except for things like moving services to layers, as described elsewhere in this document). If you were considering using `ServiceType` to define a custom kind of pluggable service, be aware that creating new subclasses of `ServiceType` is essentially deprecated - you can now use any superclass (or perhaps interface) you like, and lookup will handle it. Existing subclasses such as `Executor` and so on of course remain for compatibility reasons.

### XML entity resolution and processors installed via layer

For 3.3, there is a more efficient and powerful way to add both entity resolution and cookie processors for XML files based on public ID.

- Entity resolution. In 3.2 it was possible to add declarations of known entities (in most cases XML DTDs) to the system, using an XML file in a special format. For example, if you had your own DTD for some purpose and wished to ensure that at least from within the IDE a local copy would be used instead of accessing the network, an XML file could be added to the services area with the DTD given by `-//NetBeans//Entity Mapping Registration 1.0//EN`.

  This method continues to work in 3.3 but is deprecated: it adds some overhead at startup to parse all such entity declarations, and there were some possible race conditions. Instead you may register entities according to their public ID directly in a layer: create a file containing the entity itself and give it a special name beneath `xml/entities/` computed from the public ID. This is more efficient and safer. See `EntityCatalog` for details.

- Processors. In 3.2 you could add your own cookies to XML files without actually recognizing the files using a data loader. This was done with an `XMLDataObject.Processor` implementation, registered programmatically via `XMLDataObject.Info`.

  For 3.3 this is deprecated, as a typical processors may never be used in a given IDE session, and it caused too much work at startup to register them all programmatically. Instead the folder `/xml/lookups/` is used, with a file naming convention similar to that given above for entities. But the file names end in `*.instance` and should give an instance of one of the following things:

  1. `Environment.Provider`. This is the best option, new in 3.3. It permits you to provide a lookup for the XML file which may serve cookies as it likes, including changing the cookies on the fly.

  2. `XMLDataObject.Processor`. This is deprecated for 3.3.

  3. `XMLDataObject.Info`. Also deprecated for 3.3.

  If you were providing a special `DataNode` for the XML file, this is deprecated but no better alternative yet exists in 3.3 - Looks will probably be used for this in the future. In the meantime it will still work; you can use `XMLDataObject.Processor` subclassing `DataNode`, or provide results from a lookup query on `Node`. Either way, register the object in the layer as above.

  The Services API has additional information on associating cookies with XML files.

### Autoload modules

A new feature introduced into the NetBeans 3.3 core module system (though not officially covered by the Modules API) is that of autoload modules. It was observed that a number of modules simply function as libraries with no intrinsic value to the user, but are needed by "real" modules. Using module extensions (`modules/ext/` and referencing via `Class-Path`) is not suitable: as of 3.2, modules do not automatically share extensions even when the file name is the same, meaning the JAR would be loaded twice; and extensions are not full modules, so they cannot register basic services in a layer, and so on.

So autoloads were introduced. An autoload module behaves exactly like ordinary modules except where enablement is concerned. It has no permanent enablement status; it is turned on automatically when the first non-autoload module to depend on it is turned on, and turned off automatically when the last such real module is turn off. Neither the user nor code can turn on or off just the autoload. It will be listed in a segregated category of the Modules node.

If your module built for 3.2 matches these criteria it may be better used as an autoload:

1. Turning it on by itself, without something else to use it, would be pointless for the user.

2. You have made it into an extension, or considered doing so, in order to be able to share it among several first-class modules.

3. It has no independent user interface, or it does but this UI is just a container to be filled by other modules.

4. Most of the module is an API of some sort.

To make it an autoload is easy: place it in the `modules/autoload/` folder of the IDE installation. It may have extensions and so on like regular modules, e.g. `modules/autoload/ext/`.

### Use hints to control property editors

The entire `org.openide.explorer.propertysheet.editors` package is deprecated, save perhaps generic interfaces such as `XMLPropertyEditor`, `EnhancedPropertyEditor`, and `EnhancedCustomPropertyEditor`. Any code which was using a specific property editor implementation from this package (such as `FileEditor` or one of its subclasses) should stop doing so for 3.3, and new code should not be written using this package.

There is a cleaner system in place for controlling the UI of property editors. Rather than explicitly creating a `PropertyEditor` implementation, you rely on the core and the search path to provide one according to property type. Controlling aspects of the editor is done using hints, name/value pairs which may be applied either to `PropertyDescriptor`s in a `BeanInfo`, or to `Node.Property`s when using the Nodes API. A number of hints for common property editors are already defined, and more will be defined as they are needed.

See the Explorer API for details on how to use these.

Here is an example of replacing the deprecated `DirectoryOnlyEditor` with the default editor for `java.io.File` plus a hint to use directories. It is similar to that used in the bean info for `LocalFileSystem`:

    PropertyDescriptor rootDirectory = new PropertyDescriptor("rootDirectory", LocalFileSystem.class);
    // These are documented in the Explorer API under java.io.File:
    rootDirectory.setValue("directories", Boolean.TRUE);
    rootDirectory.setValue("files", Boolean.FALSE);
    rootDirectory.setDisplayName(/* ... */);
    rootDirectory.setShortDescription(/* ... */);

`j2eeserver/src/org/netbeans/modules/j2ee/impl/ServerExecSupport.java` also demonstrates creating a `Node.Property` editing `DataObject`s with a given cookie. (It could probably also use the `cookies` rather than `dataFilter` hint.) `ant/src/org/apache/tools/ant/module/nodes/DataTypeNode.java` in `FileProperty` demonstrates creating a `java.io.File` again, but this time specifying a base directory to resolve filenames from. The Services API includes an example of customizing the editor for `java.lang.Object`.

Also if you are displaying a custom GUI component in which you would like to embed something akin to the Property Sheet or the GUI customizer for a property, avoid directly creating the embedded editor, if it is even available from the APIs. You want to take advantage of future improvements in the editor, and pick up whatever the core search path has to offer. So use `PropertyPanel` which is a neat way to reuse the property sheet code for editing a property.

## Performance Optimizations

NetBeans 3.3 release is targeted mainly on performance and stability. For performance improvements, some compatible changes in API were done to allow modules to be less aggressive during the IDE startup. The standard NetBeans modules were changed accordingly to these changes but compatibility was ensured for other modules. The other modules work in NetBeans 3.3 without modifications but they are not so kind to the user's computer resources so it is desirable to change them to use the new APIs as well. The following paragraphs show the key areas which should be changed, and the methods for checking modules performance.

### DataLoader changes

DataLoaders needs to be loaded into the IDE and initialized during the startup. They are necessary for the IDE functionality and may be considered entry point for file-type oriented modules. But there are things tightly coupled with DataLoaders which are not necessary until the DataLoader spot its file.
The first thing is `DataObject` for given DataLoader. Resolving DataObject too early can bring a lot of unneeded stuff into the IDE, but it was a common use-case of the DataLoader because the DataLoader have to pass its DataObject Class to the super constructor. As of OpenAPIs 1.10, it is possible to pass DataObject Class's name instead of the DataObject itself, so you should change your DataLoader constructor from

    public TXTDataLoader() {
        super(TXTDataObject.class);
    }

to

    public TXTDataLoader() {
        super("org.netbeans.modules.text.TXTDataObject"); // NOI18N
    }

See also API changes
DataLoaders also don't have to set actions and display name during the initialization. For this purpose, two methods were added some time ago, even before NetBeans 3.2 release but they were not much used before. These are defaultActions() and defaultDisplayName(). You should remove calls to setActions() and setDisplayName() and override the above mentioned methods instead.
Example:

    protected void initialize() {
        setExtensions(...);
        setDisplayName(NbBundle.getMessage(TXTDataLoader.class, "PROP_TXTLoader_Name"));
        setActions(new SystemAction[] {
                            SystemAction.get(OpenAction.class),
                            SystemAction.get(FileSystemAction.class),
                            null,
                            SystemAction.get(CutAction.class),
                            SystemAction.get(CopyAction.class),
                            SystemAction.get(PasteAction.class),
                            null,
                            SystemAction.get(DeleteAction.class),
                            SystemAction.get(RenameAction.class),
                            null,
                            SystemAction.get(SaveAsTemplateAction.class),
                            null,
                            SystemAction.get(ToolsAction.class),
                            SystemAction.get(PropertiesAction.class),
        });
    }

should be changed to

    protected void initialize() {
        setExtensions(...);
    }

    protected String defaultDisplayName() {
        return NbBundle.getMessage(TXTDataLoader.class, "PROP_TXTLoader_Name");
    }

    protected SystemAction[] defaultActions() {
        return new SystemAction[] {
                            SystemAction.get(OpenAction.class),
                            SystemAction.get(FileSystemAction.class),
                            null,
                            SystemAction.get(CutAction.class),
                            SystemAction.get(CopyAction.class),
                            SystemAction.get(PasteAction.class),
                            null,
                            SystemAction.get(DeleteAction.class),
                            SystemAction.get(RenameAction.class),
                            null,
                            SystemAction.get(SaveAsTemplateAction.class),
                            null,
                            SystemAction.get(ToolsAction.class),
                            SystemAction.get(PropertiesAction.class),
        };
    }

See also API changes

### SystemOption usage

Modules often have persistent configuration and it is often implemented as a `SystemOption` subclass. The `SystemOption`s singletons were previously mentioned in module's manifest as `OpenIDE-Module-Class: Option` and their serialized state was loaded during the IDE startup, although it was not necessary in most cases. Now, you can move the option declaration into the layer and it will be deserialized the first time you'll ask for it. This also means you have to be careful to not reference the option too early. Common mistake is to place static reference to the option instance somewhere where it would be touched too early, like

        static MyOptions OPTIONS = (MyOptions)SharedClassObject.findObject(MyOptions.class, true);

inside a `MyNode` class or something like this.
In short, you should isolate the access to the SystemOption instances by lazy getters or lazy loaded classes. It you believe you can initialize your module without `SystemOption` and your `SystemOption` is still loaded, place a `Thread.dumpStack()` in a static initializer of your SystemOption, it will tell you who references it.

### Services declaration

The similar issue as with `SystemOption`s is with `ServiceType`s. `ServiceType`s hold their configuration serialized and were used to be deserialized/initialized during the IDE startup. You should move all services from the module's manifest to layer, it will prevent the services from eager initialization.

### WindowSystem changes

Modules which define their own Workspace or Mode, or starting with some TopComponents open were used to do this programmatically from their ModuleInstall. It is wrong from two perspectives: Why should the IDE create the window with its content when it will be hidden for most of the time, and why this thing have to be performed on every IDE startup (common case). This is solved by the new WindowSystem implementation which allows declarative specification of Workspaces, Modes and TopComponents allowing the module author to specify more docking constraints for the modes and TopComponents.
You should replace the layout creation code in ModuleInstall by XML documents placed at proper locations in the module's layer.
See the Window System API.

### ModuleInstall cleanup

There is a generic guide why to cleanup `ModuleInstall`s.
After all of the above, your `ModuleInstall.restored()` should be empty in a lot of cases. If it is not the case, you should try to come up with some replacement solution. Be creative. Just think about what you're doing in the `ModuleInstall`, what is the impact on the IDE startup time, number of classes loaded on the startup and the memory footprint of the IDE. Then think whether it is necessary to do it during startup, how can you get it out of `ModuleInstall` and so on. There it one thing to think about: Your module will NOT be really used by most of the users of the IDE with your module enabled.

We can't cover all the possibilities in this guide, so I'm placing here an example for removing hooking into other modules: The cases where you're hooking some functionality in other module code can be replaced by lookup, but it requires cooperation with the other module's author. This was the case with Beans and Javadoc modules hooking their `NodeFactory`s into Java module's Nodes. Now they only place instance files into their layers and Java module will pick up the instances (using a `FolderInstance` over some negotiated folders, namely `NodeFactories/java/explorer` and `NodeFactories/java/objectbrowser`) as soon as it will need them, which means way later than with direct registration. This kind of communication can be developed between other modules as well, but there is no generic one size fits all recommendation.

### BeanInfo implementations

This is not an upgrade issue but surely thing you should care of.
There are some BeanInfo classes in nearly all modules. The problem with their implementation is that they are "over-cached" most of the times. The BeanInfo is a class that is brought inside the VM mostly for one-time usage like deserialization or IDE configuration so it should be optimized for size, not the speed. Holding of tons of reflective information in static fields is not an option for such a class. See for example issue #14938 for more on this topic. You could look for rewrite example here
In future, we plan to replace standard BeanInfo lookup mechanism by a XML based bean descriptions but it is not fully specified yet.

### PropertySupport.Reflection

This is another thing that should be considered while rewriting the module. There is a lot of subclasses of `PropertySupport.ReadWrite/ReadOnly`. In most cases they can be replaced by using `PropertySupport.Reflection`. The reason is simple: the less classes are loaded in the VM the better.

### Static resource bundles

You should avoid keeping static references to resource bundles. `org.openide.util.NbBundle` is intended to centrally manage the bundle cache anyway.

    // UNDESIRABLE:
    private static ResourceBundle bundle;
    private synchronized static getText(String key) {
        if (bundle == null) {
            bundle = NbBundle.getBundle(ThisClass.class);
        }
        return bundle.getString(key);
    }
    public getSomeText(String something) {
        return MessageFormat.format(getText("FMT_foo"), new Object[] {something});
    }

    // BETTER AND EASIER:
    public getSomeText(String something) {
        return NbBundle.getMessage(ThisClass.class, "FMT_foo", something);
    }

# Pre-3.3 Changes

There are a few older changes which were available already in 3.2 but sufficiently young that many modules may not have picked up on them, so a few of these are listed for completeness.

## Desirable Changes in Modules

Consider making these changes.

### Image caching and badging

Most loading of images, such as from `BeanInfo.getImage()`, loads an icon from a module resource path. The JRE provides a few caching techniques, such as those in `Toolkit` and `SimpleBeanInfo`, but they are not great with memory management. Please use the NetBeans standard cache manager: `Utilities.loadImage(String)`.

Your module should never load an image in the static initializer of some class, just load it on demand using the cache:

    // This is bad:
    static Image myicon = ...;
    public Image method() {
        return myicon;
    }
    // This is better but never collects the image:
    static Image myicon = null;
    public Image method() {
        if (myicon == null) {
            myicon = ...;
        }
        return myicon;
    }
    // Better yet, though JRE cache manager is not the best:
    public Image method() {
        return Toolkit.getDefault().getImage(...);
        // similar for SimpleBeanInfo.loadImage(...)
    }
    // Best:
    public Image method() {
        return Utilities.loadImage("my/pkg/resources/something.gif");
    }

If you are doing icon badging, that is placing special overlays on a basic icon to indicate statuses such as "uncompiled", "in error", "needs checkout", and so on, then you can do this best using the badge management API, which is easy to use and works well with the image cache (both basic images and generated composites are cached sanely): `Utilities.mergeImages(...)`

### Short and long descriptions and categories for modules

All modules ought to have in addition to the display name a short description (tool-tip-length); long description (paragraph-length); and a display category (phrase selected from among some known categories). This will help the user understand what the module does and whether it is important; such information is displayed under the Modules node as well as in the module configuration panel of the Setup Wizard.

For 3.3, such information is all localizable and should go into a bundle, so for example:

    OpenIDE-Module-Name=My Module
    OpenIDE-Module-Short-Description=This module performs one simple task relating to something.
    OpenIDE-Module-Long-Description=\
            This module is a complete solution for developing something objects. \
            It can be used in two modes, one to generate things, and one to display them. \
            You may want to use it in conjunction with the Power Something module.
    OpenIDE-Module-Display-Category=Data Types

### Nicer-looking wizards

Wizards got a face lift - you can customize a number of aspects of wizard GUI, such as creating a list of steps to be performed in the left margin of the wizard. All wizards used in 3.3 should try to look pleasant to the user, especially in the list of steps. Pending official documentation, see the UI website.

### Use `ErrorManager` for logging

Do not use `System.err.println` for keeping a trace of what your module is doing. There is a better way:

    static final ErrorManager err = TopManager.getDefault().getErrorManager().
        getInstance("org.netbeans.modules.mymodule"); // NOI18N
    // ...
    if (somethingWeirdHappened) {
        err.log("something weird happened here");
        // continue with it
    }
    if (isStrange(result)) {
        if (err.isLoggable(ErrorManager.UNKNOWN)) {
            err.log("strange result: " + formatForDebugging(result));
        }
        // deal with it
    }

You can log messages to the system log file (and also check whether one will be logged before doing some expensive calculation). To turn on logging for your module, just add this to your command line or `ide.cfg`:

    -J-Dorg.netbeans.modules.mymodule=0

You should see in `system/ide.log` e.g.:

    [org.netbeans.modules.mymodule] something weird happened here
    [org.netbeans.modules.mymodule] strange result: Result<....>

You can also set the level to -1 to get output on the console too.

Regardless of whether you use it for logging, `ErrorManager` should be used by all modules for several purposes:

1. Adding information to an exception. Use `annotate`. You can add unlocalized information to help debug it, or localized information (preferably with a severity level) to present it comfortably to the user, if it is expected that a user action could cause it.

2. Changing an exception type. Use `annotate` or `copyAnnotation` before rethrowing to preserve the original stack trace.

3. Reporting an exception you have caught. Use `notify` to include all information available - never `printStackTrace` which bypasses the manager and can lose information.

See the documentation for `ErrorManager` for more details.

# Helpful Performance Tools

These tricks can help you find areas of your module that need performance work.

## Startup performance logging

If you'd like to see how does your module perform during the startup, turn on the startup profiling by using the command line switch `-J-Dorg.netbeans.log.startup=print`
You'll see cut-through the startup process in the following format:

        @10116 - module preparation started
            @10276 - prepared org.netbeans.modules.text/1 dT=160
    	...
            @11104 - prepared org.netbeans.modules.vcs.cmdline.compat/1 dT=1
        @11105 - module preparation finished, took 989ms

where the @10116 is the timestamp from the start of logging (early in the startup phase), there are bigger section ending with label in the form `@timestamp - label, took {time for the whole block}ms`. The bigger blocks are nested and also contain checkpoints which show the time from the latest checkpoint in the form of `dT={time}`
The most important parts for module authors are:

`@10555 - prepared org.netbeans.modules.editor/1 dT=73`: This covers enabling the module's ClassLoader with dependencies, parsing manifest, loading ModuleInstall class and possibly calling `ModuleInstall.validate()`. In most cases you can't affect this much.

`@14272 - sections for org.netbeans.my.module/1 loaded dT=21`: covers installation of module actions, nodes and loaders.

`@19795 - ModuleInstall for org.netbeans.my.modules/1 called dT=171`: covers ModuleInstall.restored().

You should also check the time spent in `Project opened` and `Main window opened` checkpoints with and without your module.

## Class loading listing

Class loading is one of the most time and memory consuming thing on the IDE startup, so you should avoid loading unnecessary classes during the startup. You can use JVM switch `-J-verbose:class`, grepping the output for classes of your module and also checking the impact of enabling your module on other classes (wc -l, diff). The most powerful is the combination of both the switches which will show you where are the unnecessary classes are loaded so you can better investigate why are they loaded.

Have fun with the new release of NetBeans! Send feedback to `nbdev@netbeans.org`.

@FOOTER@