How does NetBeans recognize files?

Apache NetBeans Wiki Index

Note: These pages are being reviewed.

A lot of applications show some UI that displays folders of files; also a lot of NetBeans UI is created by showing virtual files in the configuration filesystem. When a folder is expanded in the UI, files of known types have their own icons, menu items, actions, properties, child nodes and behavior.

The way NetBeans detects files is this:

  • The "files" being shown are [DevFaqFileObject FileObject]s - wrappers around, or in the case of configuration files, typically wrappers around data stored in a virtual filesystem, such as inside XML files in modules.

  • What you’re actually seeing is `Node`s, which are the things that provide actions, localized names, etc. to files or other things.

  • Between Node`s and `FileObject`s are `DataObjects. A DataObject is like a FileObject, except that it knows what kind of file is being shown. There are different subclasses of DataObject for files with different file extensions, XML files with different DTDs, etc.

  • The various DataObject subclasses are provided by modules which implement support for particular file types (for example, the Image module makes it possible to recognize and open .gif and .png files), provides the icon for them, etc.

  • The "type" of a file is a MIME type, just as email attachments use - for example, a .java file has the MIME type text/x-java and a .gif file has the MIME type image/gif.

  • A module which wants to implement support for a file type registers a MIMEResolver that is given a chance to claim a file the first time the system sees it (typically you do not write your own MIMEResolver, you just declaratively register a MIME type against a file extension or XML DTD).

  • That module (or some other one) also provides a DataLoader — a factory for custom DataObjects that are specific to this file type. The DataObject in turn provides the Node (icon, etc.) that you see in the user interface.

So, to recap — when you expand a folder, and the system goes about showing a tree of nodes representing files, what happens is:

  1. The child FileObjects of the folder are listed

  2. Each child FileObject is checked by extension (and DTD in the case of XML files) against registered MIME types / MIMEResolvers.

  3. Once the MIME type is known, the DataLoader for that MIME type is found

  4. The DataLoader is asked for a DataObject for the child FileObject

  5. The DataObject is asked for its Node delegate

  6. That Node’s icon and display name are shown in the UI

The results of these operations are cached as long as they are in use. For any file on disk, there is at most 1 FileObject. For any FileObject there is at most one DataObject (one DataObject may represent 2 files, but that is another story). Each DataObject has exactly one Node which presents that DataObject to the user.

In other words:

  • FileObjects represent "dumb" files on disk or elsewhere - a path, input and output streams, but no concept of what the file represents beyond folder versus data.

  • MIMEResolvers know how to tell what MIME type a file is. They have an order in which they are asked to claim a file.

  • DataLoaders are registered against various MIME types. When a DataObject for a file is needed, the DataLoader for that MIME type is asked to make one. What it will make is a DataObject subclass that understands something about the file, its data, etc. For example, a DataObject for a .properties file might provide a way to get a java.util.Properties object representing the file’s contents.

  • DataObjects are like FileObjects, except they understand what the file is, or its contents, and may provide ways to programmatically manipulate the file, such as opening a text or graphical editor.

  • DataObjects have Nodes.

  • Nodes add human-friendly attributes such as localized names, popup menu items, properties, tooltips, etc. to the more programmer-friendly Nodes.

Note: As of NetBeans 6.9, it is often not necessary to subclass DataLoader - a generic DataLoader can be created by the system, which knows the DataObject subclass to create. Simply use _'New File > Module Development > File Type' to generate such code._