blob: baca3bf6b3c4f39aacadd2ae58a69723acdfa7c7 [file] [log] [blame]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- -*- xhtml -*- -->
<title>Introduction to the NetBeans APIs</title>
<link rel="stylesheet" type="text/css" href="https://netbeans.org/netbeans.css">
<meta name="AUDIENCE" content="NBUSER">
<meta name="TYPE" content="ARTICLE">
<meta name="EXPIRES" content="N">
<meta name="author" content="gwielenga@netbeans.org">
<meta name="indexed" content="y">
<meta name="description"
content="A short guide to creating, installing, modifying, and reloading a simple NetBeans Plug-in Module.">
<!-- Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. -->
<!-- Use is subject to license terms.-->
</head>
<body>
<h1>Introduction to the NetBeans APIs</h1>
<p><small><a href="mailto:nbdocs_feedback@usersguide.netbeans.org?subject=Feedback:%20NetBeans%20IDE%20Introduction%20to%20NetBeans%20APIs">Feedback</a></small></p>
<p>API stands for "Application Programming Interface".
The word "interface" indicates that the API lives between at least two different subjects.
For example, the internal structure of the application could be seen on one side, while the foreign applications that make
calls into it are found on the other. Or there is the programmer (or team) developing the application and its API on one side and
on the other side are the the programmers using it. The important observation is that in both cases these two sides are
<i>separated</i> - either compiled separately or developed in completely different groups with their own schedules, goals and needs.
<p>An API is everything that another team or application can depend on:
<ul>
<p><li><b>Method and field signatures.</b> Communication between applications
is usually about calling functions and passing data structures between
each other. If there is a change in the names of the methods, in their
arguments or in structure of exchanged data, the whole program often
does not even link well, nor it can run.
<p><li><b>Files and their content.</b> Many applications read various files
and their content can influence their behaviour. Imagine one application
relying on another to read its configuration file and modifying
its content prior to invoking the application. If the format of the file
changes or the file is completely ignored, the communication between
those applications gets broken.
<p><li><b>Environment variables.</b> For example, the behavior of CVS
can be influenced by the variable <tt>CVSEDITOR</tt>.
<p><li><b>Protocols.</b> Opening a socket and being prepared to interpret
streams sent there, or putting or reading a data to clipboard or during
drag and drop again, establishes an API that others can depend on.
<p><li><b>Behavior.</b> What the program flow
looks like - what is the order of execution, what locks are being held
during calls, in which threads a call can happen, etc.
<p><li><b>L10N messages.</b> Because the localization to a certain language is usually developed and
distributed by somebody other than the person that writes the code, yet both of
them have to use the same keys (<tt>NbBundle.getMessage
("CTL_SomeKey")</tt>), there is inherently a contract between
the writer of the code and the translator - an API of sorts.</ul>
<p>
<p>This document provides an overview of the NetBeans APIs, together with related resources
that you can use to get to know them better.
<h2 class="tutorial">Actions API</h2>
<p>This API is a standard representation of the actions a user can invoke. It provides
an interface to such IDE elements as toolbars, menus, and keyboard shortcuts -
allowing third parties to create actions that are sensitive to context and invocable in
more than one way. Special superclasses are sensitive to selected nodes and cookie
sets - the module author decides if these apply. The Actions API offers the ability to
write the action once, and have it automatically apply as appropriate. For example, a
user action might show up in both a toolbar, and be selected by a keyboard shortcut,
all from the same implementation.
<p>All actions in the IDE are subclasses of SystemAction, which extends the Swing
action API to interact smoothly with the IDE. The Actions API provides abilities
such as context sensitivity, callback support, automatic presentation devices in
menus and toolbars, and a few other features used by the IDE.
<p>Actions are typically presented in popup menus, or attached to a component such as
a window, node, or data object.
<p>
<br />
<h2 class="tutorial">DataSystems API</h2>
<p>Developers use this API primarily to cause the IDE to recognize new data types,
such as UML model files, add user-visible actions to nodes representing a custom
or standard type, implement templates, and so on. Data objects may also represent
logical groupings of physical files where appropriate. <tt>org.openide.loaders</tt>
associates files together into groups and assigns types to data, creates data
objects from files, and defines how cookies attach behavior to these objects.
<tt>org.openide.cookies</tt> provides a design pattern for attachable behaviors
for data objects and nodes.
<p>The loader mechanism is responsible for scanning files in a directory on disk,
ignoring files irrelevant to the IDE, and grouping the rest into logical chunks. The
loaders also determine what type of data each file represents. This scanning is
performed by asking each registered data loader whether or not the given file(s)
should be handled. The first loader to recognize a file takes ownership of it, and
creates a matching data object to represent it to the rest of the IDE.
<p>Loaders are used in the IDE to group associated files together into a data object.
Within the IDE, a data object is represented by a single node, and has a single set
of actions applicable to it. Unlike a bare file object, a data object holds a number
of behaviors. For example, it can hold cookies providing various behaviors, have
an associated opened editor, be specified as a template, and may provide special
procedures to be run when it is moved or renamed.
<div class="indent">
<h3 class="tutorial">MultiFileLoaders and UniFileLoaders</h3>
<p>Multifile loaders are able to recognize multiple files at once and create a data object
from them. All data objects have a primary file that is representative of the data
object and is often used to identify it. As well, these multifile loaders may have
any number of secondary files. The basic mechanism used is that the loader pool
will pass file objects to it in an arbitrary order; the loader may get a primary or
secondary file first. Either way, it must recognize that it belongs to a cluster; find
the primary file if it got a secondary one; and create a new <tt>MultiDataObject</tt>
containing the supplied file as an entry. When other files in the cluster are passed to
the loader, it must create new entries in the same multidata object, to indicate their
association.
<p>Of course, a single-file loader is simpler, and is likely to be more commonly
used since the majority of file types make sense by themselves. The default
implementation simplifies the creation of a subclass that recognizes only certain file
extensions. Note that the standard UniFileLoader is actually a special type of
MultiFileLoader in that it recognizes only one file. UniFileLoader actually
creates a MultiDataObject when it recognizes its file. Normally the
UniFileLoader is used for most purposes, and the behaviors in
MultiDataObject are generally available as defaults.
<h3 class="tutorial">Cookies</h3>
<p>A cookie is a design pattern that separates the presentation of implementation of
some interface from the actual object that implementation ought to be associated
with. It is a convenient way of removing the requirement that all interfaces
presented by the cookie holder - usually a data object or node - must be
actually implemented by the Java class of the object.
<p>When cookies are attached to a data object, they define what properties and
behaviors are available. For example, if a data object is editable, attaching an editor
cookie defines editable actions. EditorCookie deals only with opening the
contents of a file as text within the window. Cutting and copying text within the
window is a function of the editor, as opened by the editor cookie. Note that the
more general OpenCookie could be added to a file to open something else, such
as a thumbnail (as is done in the standard IDE for image files).
<p>For purposes of marking a cookie as such, the cookie interface (or an abstract class)
should extend <tt>Node.Cookie</tt>. Other than that, there are no requirements as to what
makes a valid cookie. Typically a cookie provides a small set of abstract operations,
such as "opening", "compiling", "searching" and so on. Using cookie sets, it
is convenient to dynamically add and remove cookies from a holder. This is
appropriate for holders of cookie types whose applicability may vary over time.
<h3 class="tutorial">Cookie Supports</h3>
<p>While it is possible for any data object or node to offer ad hoc support for any given
cookie if it has a special way of doing so, more commonly there is a standard way
(or set of ways) that a particular cookie is likely to be implemented. It is the primary
job of the holders to declare that they want to use a cookie. In this case, the standard
implementing class is called a support, and typically its constructor will provide an
association to the holder in some fashion. The support itself will determine what to
do with the holder object when invoked.
<p>This is why the IDE has supports - implementations of cookies - that provide the
IDE’s standard way of handling something and which anyone is free to reuse. For
example, the editor cookie has the corresponding support "editor support." The
editor cookie says this document can be opened, this object can produce a document,
and so on. The concrete class <tt>EditorSupport</tt> actually deals with the details of
telling what is modified when it should be saved, loading the object from disk, etc.
<tt>EditorSupport</tt> is physically contained in the Editor API. Most of the others are
contained in the DataSystems API under <tt>org.openide.loaders</tt>.
<p>OpenSupport is another important support. It is an implementation of OpenCookie, and provides some of the
infrastructure necessary to open the object in a window. EditorSupport extends
this. The editor support is a special case that handles opening a text file. In most
other cases, for example when providing an image editor, the module author
would directly extend OpenSupport. It provides some of the required functions
needed, such as handling the opening of a file, cloning the resulting window, and
so on. This is an abstract class - some details need to be implemented by the
module author. For example, how to actually paint the pane that is going to be
opened.
<p>Supports and cookies typically are paired off in this manner. The outer API uses
cookies in a high-level, nonspecific way, while the inner API (which is comprised of
the supports) is a concrete, useful implementation. If the support does what is needs,
extra code is not required. If the supports do not know what is needed, the cookie
may be implemented any way that obtains the desired control.
<p>Most of the standard cookies exist in the org.openide.cookies package. Many of
these have standard supports as well, frequently in org.openide.loaders. Using
the Javadoc, the most efficient way to find cookies and supports is to look at
Node.Cookie and browse the subinterfaces for implementing classes, which
are usually supports.
<h3 class="tutorial">Transferables</h3>
<p>org.openide.util.datatransfer is often grouped in the DataSystems API.
This class is an extension of things that are already in the core Java platform API.
The basic system of Java data transfer offers cut, copy, paste, drag-and-drop,
clipboards - everything typically used in authoring modules and applications.
<p>Extended transferables contain many classes. One special edition makes it easy to
support different types of data flavors at once. A data flavor is defined by the Java
specification as a type of data that can be can transferred - a string of text, file, or
image. Also, there is a provision for transferring a cluster of objects such as multiple
strings of text at once. An automatic clipboard converter, installed only by the
manifest, converts one flavor to another. It acts as a middleman between the thing
that is producing the data and the thing that is using it. Cutting, copying, pasting,
and dragging nodes between two parent nodes is supported. The module author can
cut a node in the Explorer, select another node that can accept children, and paste.
Both the source and the target may arbitrarily add extra behavior by this operation.
<p>Copying and pasting with the IDE is very configurable and flexible. It is not
necessary that both sides actually be nodes - if you write a node, you can enable
copying it as a text string. For example, if there is a RMI connection in the RMI
module, selecting that node in the runtime tab, copying, moving to the Editor and
selecting paste, will insert the code to re-create the connection in an application. This
process is bi-directional. To produce a new child node, text can be selected from
within the editor and pasted onto a node, though it is up to the developer to create
the appropriate working code for this.
</ol>
</div>
<br />
<h2 class="tutorial">FileSystems API</h2>
<p>This API represents an abstraction of the file system in the IDE. It is made up of
objects and classes that represent files, and is used to display files and directories.
It can also display the file entries contained in JAR and ZIP archives, and contains
full capabilities for version control support.
<p>The FileSystems API permits module authors to access files in a uniform manner.
For example, you may access a file and be unaware of whether a file you are using
is stored on local disk in the user's repository, in an auxiliary directory, or in a JAR
archive. Alternately, you may have reason to implement a custom file system. For
example, a vendor tool being integrated into the IDE may handle its own local or
remote storage of files in a special fashion; using this API, the rest of the IDE will
be able to seamlessly work with your files.
<p>The FileSystems API is used only to manipulate files on disk - or whatever storage
mechanism a file system may use - and makes no reference to the nature of their
contents nor how they are being used elsewhere in the IDE - beyond whether or
not they are locked. From the perspective of this API, all files consist of byte streams
(albeit with MIME types).
<p>
<br />
<h2 class="tutorial">Nodes API</h2>
The Nodes API controls the usage and creation of nodes, which are a variant of
JavaBeans that may have adjustable property sets. The Nodes API also provides
cookies and actions.
The functionality in the Nodes API includes operations such as browsing of nodes;
cut, copy, paste, and reordering; display characteristics, both icon and available
properties; and actions that may be taken on the node, such as in a context menu.
A rich API deals with children of nodes, and access to changes of information is
provided.
Using the Nodes API:
<ul>
<p><li>
The icon for a node can be defined, including the display name, behavior on a
rename attempt, copy, drag, and so on. There is also a pop-up dialog customizer.
<p><li>
Properties may be displayed as shown in the property sheet. Every node can
define what properties to present.</ul>
Each data object can designate a single node to represent it. For example, a Java
source file node displays the source name and properties, as well as configured
items on the execution tab. The interaction of the node to the DataSystems API
is responsible for all these capabilities and representations.
Nodes are not static data - they are live components of the IDE. So actions taken
in one part of the system will frequently cause open Explorer views to refresh to
display the new node structure. For example, typing in a new method in a class,
after a moment’s delay to reparse, will cause a new method node to appear in the
tree for that class (if it was already expanded).
A node is an extension to the JavaBeans concept, adding some features that were
necessary for the full functioning of the IDE:
<ul><p><li>Full hierarchy support, including special support for various kinds of child
containment policies.
<p> <li>Actions and other IDE-specific interfaces are placed as direct Java technologylevel
API requirements - casts or introspection are not needed to determine their
availability.
<p><li>Certain basic operations on nodes, such as creating a serializable form of the
node, or cut-and-paste support, are implemented as an abstract base class.
Concrete subclasses then provide the easiest and most common implementations
of these operations.</ul>
</ol>
</div>
<br />
</body>
</html>