【Netbeans Platform】Cooking with the NetBeans Platform v 5.5
Cooking with the NetBeans Platform v 5.5
Practical API Design Confessions of a Java Framework Architect.rar
1. About these notes
1.1. Why NetBeans Platform?
I have always wanted to take a deep look at the NetBeans Platform as a mechanism for building large complex Swing applications. During this summer I have allocated some time to do so and the fact is that it's just fantastic!
NetBeans is between six and eight years old. Sun adquired NetBeans on 2000, but the software was alive at least two years before that. That's a long time for a software project, so it must be a good piece of software, right?
During my trip around the NetBeans Platform I have found excellent pieces of software. Many of them can be used outside NetBeans, so you can reuse them in your projects. All NetBeans code is released under the CDDL, so you can now use it in both free or commercial products. That's just fantastic!
1.2. Why these notes?
Well, while learning how to use the NetBeans Platform to build applications, I often found myself a little bit lost. And although things have changed a lot during the last few months (more blog entries, more tutorials, more documentation) and will probably change in the near future, information is not always easy to find.
So I decided to build some software on top of the NetBeans Platform and explain how I'm doing it (and showing the problems I find in the way, too). That would make easier for you to get started with NetBeans as well.
I was also interested in learning DocBook as a publishing platform, because all documents are created in XML (and that is a great advantage for me, for diifferent reasons) and then transformed into HTML or PDF (among other formats). I wanted to verify myself how powerful DocBook is, and I am greatly impressed. The result is this you're reading!
I also wanted to build an IDE for Scheme, one of my favourite programming languages. Scheme allows you to program in an imperative way, but you have also functional programming on your tips. You have tail recursion, continuations, closures and lots of cool stuff. And it's extremely simple too. But, although there're different IDE's out there, I wanted to build one that could talk directly with Java, my other favourite programming language.
So these notes are about how I'm doing an IDE for Scheme on top of the NetBeans Platform, and are being written using DocBook. That covers all those three objectives: learning the NetBeans Platform, building a Scheme IDE and taking DocBook to the limit.
1.3. About these notes
1.3.1. Your comments, please!
These are interactive notes. There's a basic commenting mechanism at the bottom of each page, that shows a list of the last ten or twenty comments for each page. You can post your suggestions, complaints and ideas on each page, if you like. If I'm wrong in anything I'd love to know why. That way we can learn together.
1.3.2. Changing stuff
These notes will be changing all the way through. I mean I may be able to rewrite a whole page, or change certain parts of it.
The notes will have a publication date, so you can track when the page has been published. And, of course, I will provide some RSS and Atom feeds (linked to my blog at the moment) so you can track changes and advances easily.
1.3.3. Finding things easily
DocBook is cool for building indexes. I have marked certain parts of the notes with index terms, so building an Alphabetical Index is very easy. I think this is a good idea for documenting the process, because things are easier to find then. All pages have a permanent link to both the Table of Contents and to an Alphabetical Index.
1.3.4. Ugly figures?
One additional objective I didn't mention previously is to learn how to use The Gimp, an image manipulation program for Linux as well as a little digitizer card I was given. I'm not that good at using The Gimp (because it has a somewhat weird user interface) but I like painting. So be warned that figures will evolve as I get used to The Gimp.
So no jokes on figures, please ;-)
1.3.5. Proposed structure
I would like to explain why I like NetBeans as a development platform. From the perspective of a software architect. So I thought I could do this in a first section. Then I realized that this cannot be done (because NetBeans is so big) so I decided to explain a little bit about modules as the first section, and then keep on doing the Scheme IDE, and talking about NetBeans architecture on the go.
Regarding the structure of each page, I plan to do some summary from time to time, so things are easier to understand (and to remember).
1.3.6. ¿Inglés o español?
So why am I writing this stuff in english if I'm from Spain? Well, this is probably a good way to exercise my english, right? (Which, by the way, needs some exercise! ;-)) Anyway I plan to release an spanish version of these notes in the future, as things get consolidated.
Así que un poquito de paciencia, por favor. Déjame primero ver cómo funciona esto y luego intentaré hacer una versión en castellano para los hispanohablantes. Después de todo, hacer dos versiones cambiantes de todo en inglés y español ¡sería demasiado difícil!
1.3.7. Need more info?
I will also add, from time to time, links to interesting sites where you can get more information.
1.3.8. Getting started
I am using the NetBeans IDE 5.0 for the examples. The next versions of NetBeans have much more features and are probably easier to use, but I'll stick with NetBeans IDE 5.0 at the moment. I may switch to NetBeans IDE 5.5 when it's released, but not now. You should install the NetBeans IDE (5.0) to follow the examples here. I may provide source code for certain examples, but don't count on it for everything.
If you are interested in developing with NetBeans Platform then it's probably a good idea that you join some of the NetBeans mailing lists, just in case you want to ask something or are stuck somewhere. I won't be able to help you with your projects on top of the NetBeans Platform very well (at least at the moment, I'm still learning), so you should use the mailing lists if you want help. People there are really responsive!
So there we go! Let's start building an IDE for Scheme.
2. NetBeans Module System Basics
The NetBeans IDE (version 5.0) has a ton of modules inside. More than one hundred modules! There're modules for ant, debugging, xerces, projects, class file handling, database handling, all sort of editors (java, sql, html, xml... ) and editing capabilities (bookmarks, templates, folding, syntax highlighting, ...), internationalization, configuration options, J2EE (servlets, EJBs, Web Services, etc.), XML (catalogs, editing, XSLT processing, etc.), GUI form editing, tasks lists, and many others.
That's a lot of modules, isn't it?
Now, how is it they all dance together gracefully? What is that misterious mechanism that allows these modules to handle dependencies between them, to change internally withouth the rest noticing, to be downloaded from the network automatically? How is it that these modules are initialized so fast? How is it possible that these modules can be enabled and disabled at runtime at your will?.
All those features are provided by the module management system of NetBeans (which can be used for free outside of NetBeans, by the way, so you can reuse it in any other application of your liking). This is indeed an excellent piece of software. It's so important for the rest of chapters that deserves some attention.
In this section I present some of the main charateristics of modules I've seen, from an architectural point of view. If I were you I wouldn't try to remember everything in this section now. Just read through and get acquaintanced with the terms we'll be using in the next sections. I'll try to explain the details whenever they're needed in the future.
2.1. Public APIs, exported packages, documentation and the importance of APIs
Only a part of a module is visible to the rest of modules. This public part that is visible to other modules is known as the "Module's Public API". It works basically as a Java interface: you can work with the interface (with the Public API) without knowing how the implementation works.

Separating Public APIs from implementation details of modules is a very important design decission, of course.
While developing NetBeans modules it is important to remember that you must explicitly indicate which Java packages of your project are visible to other modules. This is, you have to mark your packages as being public. (What I mean is that you have to indicate which packages conform the socket of your module, and this socket is used by the rest of modules to plug-in to yours). If you don't mark any Java packages as public, then other modules won't be able to load classes from your module, and your module (although working) won't be able to be used by the other modules.
All NetBeans modules (for the editor, syntax highlighting, etc.) have a Public API, too. That's the part of the modules that you can use. For a detailed description of all NetBeans Modules Public APIs you can see the NetBeans Module Javadoc.
NetBeans Modules Public APIs have different degrees of stability. Solid modules have a "frozen" API, that you can use safely. Modules under development may have different degrees of stability. You may use those Public APIs, but be warned that they are subject to change, and that a change in those may require changes in your code.
The NetBeans Team seems to be quite perfectionist about building APIs! Of course that's good for me, as an user of the NetBeans Platform, because I prefer programming against a well designed API. The NetBeans Team has Games on API design, Tutorials on API Development and even Tutorials on API Reviews!.
2.2. Embracing change
Of course Public APIs change (well, we all do change, right?). You can try to build a fancy, perfect API, but time will erode it in ways you haven't thought of, and eventually you'll be forced to change that API. That's life!
So instead of trying to build perfect APIs, which seems to be somewhat futile, what about embracing change?. Of course trying to write good APIs is important, but embracing change is even more important. What about marking each API with a version, so that everybody knows which API to use (and which to change)?

This is exactly what the NetBeans Platform does: build good APIs, but use versions to mark each API too. Furthermore, the NetBeans Platform allows you to version the implementation of each module, so you have different types of versions:
Major Release Version
This version is used to mark a Public API. If you change the Public API too much then you probably want to change this "Major Release Version".
Specification Version
This version is used to mark a minor change to a Public API, that remains compatible with a prior Public API. You increase this, for instance, if you have added a method in your API (but the rest of methods remain intact).
Implementation Version
You use this to mark a change in the internals of your module only. This is usually a version for your eyes only, so the rest of people using your module shouldn't be worried about implementation versions.
Don't get too worried about versions while you're beginning to work with the NetBeans Platform. As you get experienced, and start building modules that others use then you should start using versions thoroughly. This makes life easier for you.
2.3. Using... and being used: dependencies

One important aspect of a modular system is how the dependencies are handled. Most successful modular systems declare dependencies explicitly in a plain text file. Linux distros, for instance, do usually have a list of all software packages available, with versions and dependencies between those. Maven has also a good depencency tracking mechanism. Having a list of dependencies available helps you to see how important a change is (how many other modules are affected by a change). It also allows you to distribute a single module for update, and make the rest of modules to be updated automatically.
As we will see in the next section, the NetBeans IDE has an easy way to declare dependencies between modules. This makes things extremely easy for you, because you can visually track, declare and handle which modules you need.
2.3.1. I need you, you need me, I need you...
While managing depencencies, you must remember that dependencies must not be cyclic. If you have cyclic dependencies between a module A and a module B (because A needs B and B needs A) then, how are you supposed to initialize those modules? You cannot initialize A, because it needs B that is not initialized; but you cannot initialize B either, because it depends on A that has not been yet initialized. That's a problem.
The NetBeans IDE detects cyclic dependencies between modules, when you are building them, so there's no problem in doing that by accident.
If you seem to be stuck on a cyclic dependency problem then that's usually due to a bad modular approach to your software. Consider splitting modules in smaller pieces, factoring out common functionality. For instance, if you have a cyclic dependency between modules A and B, then consider extracting common functionality into another module C, and make A depend on both B and C, and B depend on C. You don't have cyclic dependencies then.
2.3.2. I need you, you need him, I don't know him
Another important thing to remember about dependencies is that they're not transitive. So if you declare dependencies with between a module A and a module B, and if module B depends on C, then A won't be able to load classes from C. Because there're no explicit dependencies between A and C.
That may seem too restrictive, but I think it's all the way round. It's easier to manage explicit dependencies than implicit ones. Remember that if you need to load classes from a module X then you need to declare a dependency with that module. It's a rule easy to remember.
2.4. Don't shout: I can't hear you anyway
Another important thing about NetBeans modules is that modules are completely isolated from each other. Each module runs in its own classloader. You can shout as much as you want from module A, that module B may not be hearing you!! That's why you may have ClassNotFoundExceptions in the beginnings (I suffered from those too, until I learned the reasons for this).

The fact is that a module A cannot load a class C from module B unless these conditions are met:
-
The class C is in a public API of module B (well, this seems reasonable: after all a class must be in the public API to be visible to other modules, right?)
-
Module A has declared a dependency with module B (well, of course, after all it's trying to load a class from module B, right?)
Although it may seem a little bit weird, the fact that one module cannot load a class from another module is indeed a great feature. This feature allows for better encapsulation and makes module-coupling explicit (because dependencies are explicit, remember?), so you cannot end up messing things up just because you're using the wrong class from the wrong module by accident.
Another great advantage of this feature is that you can bundle different versions of the same library in different modules. So, for instance, you can build a module that contains Apache BCEL 5.2 and another module that contains Apache BCEL 5.0 (for some legacy code that needs it, for instance). And them both can coexist in the same application. (Well I think this is feasible, although I haven't experimented it myself).
If you're having trouble with the module's classloader you may be interested in reading more.
2.5. One for all, and all for one!
Another important problem that we usually face when we start programming with the NetBeans Platform is module initialization.
When you're building a system with several dozen modules you should beware of startup time. Say you have fifty modules, and that each one takes 500 ms. to get initialized. If you initialize all modules at startup time then you'll need at least 25 seconds to get all modules initialized. And the user is going to get nervous about that!
What I mean is that when you're building a modular system, you should keep in mind that there're several other modules out there. And that you cannot grab all initialization time for you yourself. All modules should cooperate to reduce as much as possible the initialization time. It's one for all, and all for one!

The NetBeans IDE faced this problem several years ago (and Eclipse has faced it in release 3 too, as far as I can remember). And the NetBeans Team solved the problem using several intelligent techniques:
-
Many modules are initialized in a declarative way, so no class loading or class instantiation is performed. A plain text file, or an XML file, is parsed and the module is automatically registered into the system.
-
The fastest module to be initialized is the one that is not initialized at all, until needed. They decided to include lazy initialization mechanisms.
-
They decided to minimize initialization time as much as possible, for each module in the system, so as to work cooperatively towards a minimum startup time of all the system. The less operations your module performs at startup time, the better.
Making the joint startup time as small as possible is one of the reasons why there're different types of modules (attending to the way the module is initialized). While building NetBeans modules you'll see these types of modules:
Regular modules
These are modules that are loaded when the whole application is initialized. The initialization time of the module adds up to the whole system initialization time, so you'd better be fast initializing these.
Autoload modules
These "lazy" modules are not loaded unless someone needs them (probably at runtime). This is usually used for those modules that contain libraries. You don't really want to load a library unless you're going to use it, right?
Eager modules
This another interesting type of module. This module is loaded only if all its dependencies are satisfied. This is another intelligent way to minimize startup time. After all, if your module depends on modules A,B,C and those are not available, there's no point in loading your module, right?
2.6. Summary
So in this section we've seen some of the main characteristics of the modules in the NetBeans Platform. If you're interested in any other detail then this link explaining more details about modules may be of interest. To summarize, it's important to remember that:
Public APIs
Your modules may mark some Java packages as public. The classes in these Java packages will be made available to other modules.
Public APIs for NetBeans modules are well documented. Keep a bookmark to the API Javadoc for further reference.
Versions
Versions help you (and the users using your modules) to embrace change. There're versions for public APIs (major release version, specification version) and versions for tagging implementation details (implementation versions).
Dependencies
You must explicitly indicate which modules you need to use. After you've done that you can start using classes in the Public APIs of those modules. Remember not to build cyclic dependencies between modules.
Module isolation
Modules use their own classloaders. You won't be able to load classes from other modules unless you've declared a dependency with that module (and that module publishes the class through its Public API).
Module initialization
Try to do as little as possible during module initialization. After all you want the startup time of your application to be as short as possible, don't you?
2.7. What next?
Now, after all this theory, let's get our feet wet with some NetBeans Platform programming. Let's start by recognizing Scheme files (those that end in ".scm") in our application.
3. Adding support for Scheme files
If we are going to build a Scheme IDE we do need to detect Scheme file types, right? This section explains how to add a new file type and, by doing so, introduces some basic module building functionality in the NetBeans IDE.
3.1. Modules, Module Suites and Library Wrappers
So let's get started. Open your NetBeans IDE and select File/New Project in the menu. You'll get lots of options there. One of them is "NetBeans Plug-in Modules". Click there. You'll see three options:

- Module Project
- Module Suite Project
- Library Wrapper Module Project
Now you'll probably be confused now, right? Well, so was I. The fact is that it's not that difficult once you learn what the differences between these types of modules is. Let's see it.
3.1.1. Library Wrapper Module Projects
You use this sort of thing if you want to wrap a library for other modules to use. Note that this library is not going to be added to the resulting application for the user to use. On the contrary: this library is only for internal use in your application.
For instance, we will use this type of module to wrap the SISC Scheme interpreter inside our application, in a future section.
3.1.2. Module Suite Project
Module Suites are used to deliver a set of plain modules as a deployment unit. You can "run" a module suite, and all the modules it contains will automatically be deployed in the NetBeans Platform.
Module Suites can also be used to build a standalone application on top of the NetBeans Platform. The application will contain the modules contained in the suite (as well as any other NetBeans modules that your modules depend on). When used to build standalone applications, the Module Suites can be configured to present a custom splash screen, for instance.
While we're building the Scheme IDE, we'll be using a module suite to hold all our other modules. When finished we'll customize it with a nice splash screen.
3.1.3. Module project
This is a plain NetBeans module. It can work as a standalone module or it can be a part of a Module Suite Project.
I don't really like standalone NetBeans modules. I think all modules should live within a Module Suite Project, that way you can later on add new dependent modules easily (or even better: build a standalone application).
Plain modules are used to deliver a small amount of functionality to your applications. You can build a module to detect file types, for instance, and another module to provide basic editor support, and another one to get syntax highlighting working.
It's always a good idea to have many different small modules than having a bigger one. If you have smaller modules, that provide small functionality, it's always easier to manage dependencies between them. And, if you have smaller modules, you can enable and disable some modules (those that contains bugs, for instance) and run your application with a smaller set of modules (without syntax highlighting, for instance). Going small is probably a good idea when developing on top of the NetBeans Platform.
Prefer smaller modules to bigger onesIf you're building a complex application then use a Module Suite to hold many different smaller modules. By splitting your functionality in smaller modules you can better manage complexity, dependencies and robustness of your applications.
3.2. Building a Scheme Module Suite

So let's choose a Module Suite Project that will hold our modules. That way we can later on build a standalone application easily.
To build a Module Suite we just have to select a project name. I like using capital letters for these, so I'll call that SCHEMESUITE. It will use the NetBeans Platform that the NetBeans IDE itself is using. After entering that info, just press "Finish" and you're all set.
You'll see a new project with two folders, "Modules" and "Important Files". The "Modules" folder will contain all the modules we'll be adding to the Module Suite. The "Important Files" folder contains, well, important files! The files in this directory are extremely important, because they hold information about our Module Suite. You don't really want to mess with them (unless you know what you're doing!). So let's forget about these at the moment, we'll go into them as soon as needed.
The really important thing to know about Module Suites is that you can configure a suite by choosing the "Properties" menu in the popup menu that appears if you right-click on the Module Suite. Again we'll configure the suite later on, so let's wait a little bit until then.
Once the suite is in place we can start adding modules to it. Let's start with an important module: the one that will add file-type detection for our Scheme programs. Let's do that now.
3.3. Adding support for Scheme file types
So let's choose "File/New Project" from the NetBeans IDE menubar and let's select that "Module Project" in the "NetBeans Plug-in Modules" section.

I choose SCHEME_FILETYPE as the module name (I like capital letters for these). As you can see the module is automatically inserted into the Module Suite we have just created in the previous section.
After clicking "Next" we are prompted to enter some basic configuration details:

Code Name Base
This is a name you use to identify your module inside the NetBeans Platform. It looks like a Java package name, so you can use your preferred naming conventions for Java package names to name it. I, for instance, use my Internet domain (net.antonioshome) and then add some name for my module suite (let's say "scheme") and finally some name that identifies the module (let's say "filetype" for this module, because it is going to be used to identify Scheme file types).
Note that while you're writing your code name base some stuff changes as well. Mainly the location of your localizing bundle and your layer file (more on this later).
Module Display Name
This the display name of your module. This string will be used to show your module inside the NetBeans Module Manager, for instance. I usually choose names that are clear to me. In this case I've chosen "Scheme Filetype".
Localizing bundle and XML Layer
These are the locations of important files for the module. We'll see them in detail later on. I always accept the defaults here.
3.4. What we have now: module structure in the IDE
So we now have a Module Suite Project called "SCHEMESUITE" that contains a plain Module called "Scheme Filetype". Let's take a look at all this, and understand the basic file structure of our recently created projects. After all we'll be working with that structure all the time, so it's better to understand it now. What you have now in your IDE should be something similar to Figure 10, “Structure of module suites and modules”.

There're some interesting points to understand.
-
The "Scheme Filetype" module is contained within the "SCHEMESUITE". You can see how the NetBeans IDE has included it automatically for us under the "Modules" folder of our Module Suite.
-
See the "Source Packages" folder? Well, that's the place where our Java packages are going to reside. We'll be adding Java packages and classes in there. There's also a "Unit Test Packages" folder below, that's the place where NetBeans places our unit tests.
Notice that little tiny icon before the package name? It shows a "locked" stuff on top of the package icon, right? (Yes, I agree: this is very small, should be bigger). That small "lock" icon means that the "net.antonioshome.scheme.filetype" Java package is not public. This is, that no other modules can work with the classes under that package.
-
There's also a "Module Manifest" file there. This is a configuration file containing different important configuration data (that's why it's under the "Important Files" folder, because it's important. If it were not important then I imagine it should reside under the "Non Important Files", right? Well, but there's no "Non Important Files" folder, so it should be there anyway. Oh, I'm getting confused. Don't worry at the moment about this file. Just remember that is important and that you should not modify it directly, unless you want to do a big mess).
-
There's also a file called "XML Layer". This is important also because it's under the "Important Files" folder :-).
I'll call this the "Sandwich file". It's so important that the next section will be dedicated only to sandwiches.
3.5. But, where's the support for Scheme file types?

Yes, I know. I've entered into details and I haven't added support for Scheme file types yet. I beg your pardon. Let's get into that now.
Right-click on the "Scheme Filetype" plain module, and select the "New/File/Folder..." menu. After that, in the wizard that appears, select the "NetBeans Module Development" entry. You should see something similar to Figure 11, “New File Wizard”.
As you can see there're wizards for creating "J2SE Library Descriptors", "Actions", "Java Help Sets", "File Types", "Module Installers", "Options Panel" and many other fancy things. We'll go through many of these later on as we enhance our Scheme IDE. At the moment, and since we want to add support for Scheme files, we select the "File Type" option and click "Next".
After pressing next you'll see something similar to Figure 12, “New File Type Wizard”. The NetBeans platform recognizes files by extension. XML files, of course, have usually the same ".xml" extension, so for XML files the NetBeans Platform uses another technique: it detects the type of XML files by the namespace they use, and not by extension.

Scheme files tend to use the ".scm" file extension. Let's use that. The "MIME Type" for Scheme files can be either "text/x-scheme" or "text/x-script.scheme". I prefer the first one. Let's choose "text/x-scheme" for the MIME type. Note that you can enter different extensions here, see the help page for this wizard for more details (yes, the IDE contains interesting help dialogs, that we seldom use, right? That's sad, isn't it?).
Now, let's keep moving. Click "Next" to proceed with the next step in this wizard. You'll be presented a dialog similar to Figure 13, “New File Type (second step)”. Of course a file type should have an icon. This icon will be used for Scheme files in our IDE. I've chosen a lambda letter for these (well, of course!).

In this dialog you also have to enter to a "Class Name Prefix". I've entered "Scheme" in there (of course, again ;-)). This prefix is used as the prefix of all generated classes. Yes, this wizard generates lots of little tiny classes responsible for adding the support for Scheme file types in our future IDE. Among the generated classes and files, three are very important: the SchemeDataObject class, the SchemeDataNode class and the SchemeTemplate.scm file. We'll go through these in future sections.
Note, as well, that the wizard will modify different files under the "Important Files" folder. Among the modified files is our misterious "Sandwich file" (the layer.xml file). Note as well that the module manifest (the manifest.mf file) is going to be modified as well.
After clicking "Finish" we're all set! We now have an IDE that recognizes Scheme file types. This easy! Let's try it out! I cannot resist!
3.6. Let's run it!
So let's see how this works. First of all let's modify the "SchemeTemplate.scm" file. This is used as a template that will be used whenever you want to open a new Scheme file. Let's open this "SchemeTemplate.scm" file and write a small Scheme program:
;;
;; A sample Scheme program
;;
(display (sqrt -1))

Now, after saving this file, let's click the "Run" button. You'll see that the NetBeans Platform logo appears, and that a new NetBeans IDE is launched.
This is fantastic, isn't it? You can run the NetBeans IDE within your own NetBeans IDE!!
Now, in the new IDE, create a new project and then right-click on the project and select the "New/File/Folder..." menu. You'll have the list of available data types, including our Scheme filetype. If you create an empty Scheme file then you'll get the contents with the template above. So that's it: we've already added a Scheme filetype to our IDE!!
3.6.1. Let's run it... faster!
You may have noticed that it has taken some time to launch the new IDE. That's because we're running our module suite in the NetBeans Platform (that the IDE itself is using). And this platform contains tons of modules... that we may not need at all.
So it may be a good idea to disable some of the modules in that platform, so that we don't have to load them at startup time. This will make things faster. Let's do that. Let's disable all those fancy J2EE modules that we are not going to use: after all this is an IDE for Scheme, not for J2EE!
Close the newly opened IDE and go back to your usual IDE. Right click on the SCHEMESUITE and select the "Properties" menu. You will see something similar to Figure 15, “Disabling J2EE support on the NetBeans Platform”.

As you can see, the platform is composed of several "clusters" (groups of modules). Let's remove all the "enterprise2" cluster, by disabling its inclusion in the resulting IDE. That'll save us a little bit of startup time.
Now, run the SCHEMESUITE Module Suite again. You'll notice some speedup at startup. The newly opened IDE will still contain our Scheme Filetype module (of course!) but it won't contain support for building J2EE applications.
We'll see in future versions how to better configure our SCHEMESUITE. At the moment I think it's better to just disable the "enterprise2" cluster, since we won't be using it right now. Let's keep the other clusters because we may need modules in those.
You can experiment yourself by disabling several different clusters or different modules. You'll note that the NetBeans IDE warns you if you disable a module that is needed by different other modules (that's why it's important to explicitly declare dependencies between them, see?). Experiment with cluster and module inclusion as much as you want, and see how module inclusion affects to the resulting IDE. Note that if you disable certain modules on which our Scheme Filetype module depends, then our project won't compile any longer, and you'll have to reinclude the offending module again.
3.7. Summary
This has been a long section. In this section we've seen what the different types of modules are (Library Wrappers, Module Suites and plain Modules), what they mean. We have created a Scheme Module Suite that contains a simple Scheme Filetype module, and we have added support for Scheme file types in the resulting application.
What next? Mmm. Let me think... What about having some sandwiches?
4. Sandwiches!! (XML Layer Files)

As we have seen in the previous section, all modules in the NetBeans Platform contain a misterious XML Layer file, a "sandwich" file. This file is so important that it lives inside the "Important Files" folder. In this section we'll explore a little bit this file, trying to understand what it does and how we can take advantage of it. Don't worry if you don't get the details, as I'll explain whatever modifications are needed as I go on building my Scheme IDE. Just get used to the terms. This is a long section. You'd better fetch some sandwiches before going any further ;-)
4.1. What are sandwiches good for?
So, what can we do with those important "sandwich" XML Layer files, you ask? Well, you can do almost everything with them! Let's see some examples:
-
You can register and remove actions that contain your own logic that is invoked whenever an user action is performed. So, for instance, you can modify the menu bars, menus and menu items of NetBeans (that refer to actions).
-
You can register and remove JDBC drivers and connections in the platform.
-
You can configure lots editor functionalities, registering colors for color syntax highlighting, popup menus, special editors for your own file types, and more.
-
You can modify the Swing palette, the HTML palette (that contains HTML code snippets) or the NetBeans palette, you can add your own palette to your NetBeans Platform based application.
-
You can register and remove type of models, controllers and views so your application can handle your custom filetypes (you could build an application that handles RSS menu feed files, for instance).
-
You can register and remove options to the basic Options Dialog of your application. So, for instance, you could add a custom option dialog for Scheme-related settings (we'll do that in a future section).
-
You can register and remove XML catalogs that contain DTDs used to validate specific document types. So, for instance, you could add a DocBook catalog, so that NetBeans automagically pops-up autocompletion windows for your DocBook documents.
And there's even more! So, apart of being nutritive and good for your health, sandwich files are indeed very powerful.
4.2. How sandwich files work
As we have seen in the previous section, when creating the filetype for Scheme files, each NetBeans Platform module contains an XML Layer file. What NetBeans does at startup is to merge all those XML layer files.
How XML layer files workAt startup, the NetBeans Platform gets the XML layer file from each registered module, and then cooks a sandwich from those layers. The order of the layers is, of course, the order of initialization of modules, which, in turn, depends on the dependencies between them.
4.3. How to build your own XML layer files
Most NetBeans wizards (such as the one we used to include a filetype in our Scheme filetype module) modify the XML layer file for you, adding entries there "automagically". But of course you can build XML layer files by hand, using your preferred editor. In this section we'll see how to modify the XML layer file by hand, what its internals are, and most importantly, we'll observe how the NetBeans IDE allows you to see both your layer file and... the whole sandwich!!.
4.3.1. Watching the sandwich
This feature is extremely useful, because it allows you to see if your XML layer file is fitting correctly in the "big sandwich" of XML layer files that you are building. This saves you lots of time, because you don't have to find out what the names of the different parts of the sandwich are. Let's see this with an example using the Scheme file-type module that we created in the previous section.
So, let's open again the NetBeans IDE and see our layer and the sandwich we're building. Open the "Scheme Filetype" module that we created in the previous section. Open the "Important files" folder and expand the XML Layer file. You'll appreciate that it takes some time to open the file for you. That's because NetBeans is cooking the sandwich (mergin all tomato, cheese and other layers) and preparing it for you. You'll see something similar to Figure 17, “How the sandwich looks like - tree view”

As you can see there are two main sub-folders under our XML Layer file. The first one ("this layer") represents your XML Layer file alone (i.e, the tomato layer of the sandwich, for instance). The second one ("this layer in context") represents your XML layer file after being merged with the rest of XML Layer files, the ones coming from the platform and all the other modules, the cheese, the lettuce and all the rest of layers: the whole sandwich!
Inside the sandwich there're some entries in bold font. These represent the folders in the tree that have been added from your layer. So, if your layer contains a "Loaders/text/x-scheme" folder (as is the case), the resulting sandwich will also contain these folders, and they'll be shown to you in bold font.
Of course you can (and should) modify the layer file yourself by hand. You do that by right-clicking on the layer file and choosing "Edit". That opens the XML layer file for your module inside the editor. Note that the XML file contains a DTD declaration in there. If you modify the file by hand, it's always a good idea to validate the XML file against that DTD, just to make sure there're as little typos as possible. You can validate the XML file by right-clicking on the editor pane and then selecting the "Validate XML" option in the popup menu.
4.4. The internals of the XML layer file
XML layers are formed with three different types of elements: folders, attr (attributes) and files. These, in fact, resemble a filesystem, so that's why this mechanism is usually referred to as the "NetBeans XML FileSystem". Let's see a little bit what the components of this file are. We don't want to get into a lot of detail now, we'll see specific cases later on. Think of the following sections just as reference.
4.4.1. Folders

Folders are just a place to hold attributes and files. Folders just have a name. And that's all. Folders may be nested one inside another.
NetBeans comes with a predefined set of folders, whose names attend mainly to historical reasons. The "Actions", "Editors", "Menu Bar" and "ServiceS" folders, for instance, come bundled within the NetBeans Platform.
When you make reference to a folder in your XML layer file, make sure to use the real name of the folder, not its display name. The display name is the name that appears in the tree, but the real name (the one you should use in your XML layer file) is displayed only in the Properties window. If you use the display name in your XML layer file (and not the real name of the folder) then things won't work. See Figure 18, “Display name and real name of a folder” for details.
4.4.2. Files
Files represent files that are bundled in your module. These can be XML files, plain text files or properties files (or any other sort of file, actually). The important stuff about files is that they may also be references to instances of Java classes. This is good, because it allows you to bundle Java classes in your layer that will become a part of the general sandwich. Action objects, for instance, are usually represented as files in the XML layer file.
Files contain a name and an optional url. If the files have an url then remember that the url is relative to the location of the layer XML file.

4.4.3. Attributes
Attributes are applied to an enclosing folder or file, and represent values that affect how the folder or file work. Attributes have a name and a value, that can be primitive types (bytes, shorts, ints, longs, etc.) or strings or urls.
Attributes with the name "SystemFileSystem.localizingBundle" are special, because these have a "stringvalue" that points to a properties file used for internationalization (a Resource Bundle, actually). By adding one of these attributes to a file, for instance, you can easily internationalize it.
Attributes are also used to hide existing layers or parts of layers. Yes, layers may override each other, so a module can hide entries from a previous one. This is extremely useful, because it allows you to modify the default settings. You can, for instance, disable some entries in the Menu Bar.
Figure 19, “The contents of the XML Layer” shows an screenshot of the XML layer file.
4.5. Summary
In this section we've taken a quick bite to the XML layer and the resulting sandwich. We've learned a little bit about layers and sandwiches, what we can do with them and how they work to build a whole NetBeans Platform based application.
We've seen that the NetBeans IDE modifies the XML layer file for us, that we can modify it by hand (and that we should XML validate it before releasing our application).
In the next section (on the works now) we'll add an editor for Scheme files. And we'll have to cook our own sandwich to do that!
Keep tuned for that!
5. Bags and Rabbits (Lookup I/II)
The more I learn about the NetBeans Platform the more I like it. These NetBeans guys are admirable. And, you know what? I can even use tiny parts of the NetBeans Platform in my own applications!
In this section (and in the next one, there's lots to say about the topic) we'll learn about what I call "NetBeans' Bags and Rabbits", also known as the "NetBeans Lookup Library". A nice piece of software worth being in your bag of tricks.
5.1. So, where's my object?
When you build a complex object-oriented system you usually face the same problem: finding object instances in between all those thousand instances around in the system.

Most complex systems provide a mechanism for looking-up objects, so you can find the instance you need easily.
JavaEE application servers, for instance, provide you with a JNDI Context that you can use to locate JDBC DataSources, JMS Topics and Queues and lots of other stuff. Similar mechanisms exist in other systems. JINI, for instance, contains a Service Lookup service, used to locate JINI services.
So all complex systems have some sort of "bag" you use to store objects, and have also some sort of "look-up" mechanism you use to find objects in the bag.
And so does NetBeans! it contains a "Lookup Library" you can use to look-up objects in bags. Let's see how.
5.2. Looking-up objects
NetBeans "object bags" are represented by the "org.openide.util.Lookup" class. Looking-up objects in such a bag is quite simple, all you need is know what type of object you need. The code is as follows:
import org.openide.util.Lookup;
import my.application.MyClass;
...
Lookup bag= ... ①
...
MyClass myInstance = bag.lookup( MyClass.class ); ②
...
Collection<MyClass> myInstances = bag.lookupAll( MyClass.class ); ③
That's quote simple, isn't it?
① the declaration of "bag", a "bag of objects", represented as a "Lookup" object (we'll see later on how to get one of these).
② once you have a "bag" you just invoke the "lookup" method to seek objects by type. In the example we're seeking for an object (of possibly many objects) extending the "MyClass" class.
③ you can also get all objects extending "MyClass", you use the "lookupAll" method for that.
Use the Lookup Library in your own applications!Since the library is licensed under the CDDL v 1.0 license, you can use it both in open-source and closed-source projects. Just locate the "org-openide-util.jar" file (from your NetBeans IDE installation) and add it to the classpath of your project. That's easy, isn't it?
5.3. Complex queries, performance and... thieves!
If you now a little bit about SQL, and/or about JDBC, then you know you can submit a query to the database, and that the database in turn gives you a cursor (or a ResultSet).
NetBeans Lookups (i.e., NetBeans "bags") do also allow you to make queries and to obtain results for the queries.
Queries are represented by the "Lookup.Template" class, and results are represented by the "Lookup.Result" class. You use them like this:
import org.openide.util.Lookup;
...
Lookup bag = ... // the bag of objects
...
// A query that looks up instances extending "MyClass"...
Lookup.Template<MyClass> pattern = new Lookup.Template(MyClass.class); ①
...
// The result of the query
Lookup.Result<MyClass> result = bolsa.lookup( pattern ); ②
...
// Get all instances in the bag...
Collection<MyClass> objects = result.allInstances(); ③
...
Collection<Lookup.Item<MyClass>> objects2 = result.allItems(); ④
① here we create a "Lookup.Template", a query that looks-up all objects in the bag that extend MyClass.
② Here we get the result, a Lookup.Result.
③ We get all instances in the bag that extend "MyClass".
④ Here we don't get all instances, but a collection of Lookup.Item. This object is used to depher instantiation until the real instance is needed. This is a nice trick for performance sensitive applications.
5.3.1. Thieves, you say?
Yes. Thieves. The NetBeans Lookup Library has thieves. People that keep an eye on you: that watch you while storing things in your bag.
And those thieves are called LookupListeners, and they fire events whenever your Lookup.Result changes. Warning others that the contents of your bag have changed.
You add LookupListeners to Lookup.Results to be informed of changes in a bag. As we'll see later on this allows you to do very powerful things.
5.4. Creating bags
So we now know how to look-up stuff in our bags. We know how to retrieve objects by class. We can find a single instance of different instances, and we can use queries to obtain Lookup.Results. Good. Now, how do we create bags?
The simplest way to create a bag, a Lookup object, is to use the Lookups class (note there's a final "s" there). This is a utility class you use to create certain types of lookups. Let's see some examples (note there're many others out there, check the API!)
// An immutable bag with one string
Lookup bag1 = Lookups.singleton("Hello"); ①
// An immutable bag with two strings
Lookup bag2 = Lookups.fixed("Hello", "World!"); ②
// An immutable bag without strings
Lookup bag3 = Lookups.exclude( bag2, String.class );③
// Join two bags into a single one
Lookup bag4 = new ProxyLookup( bag1, bag2 );④
// A bag that can change
InstanceContent bagContents = new InstanceContent();⑤
Lookup bag5 = new AbstractLookup( bagContents );
bagContents.add( "Hello" );
bagContents.add( "World!");
System.out.println( bag1.lookupAll( String.class ) );
System.out.println( bag2.lookupAll( String.class ) );
System.out.println( bag3.lookupAll( String.class ) );
System.out.println( bag4.lookupAll( String.class ) );
System.out.println( bag5.lookupAll( String.class ) );
① this is the way to create a bag with a single object. The stuff in the bag cannot be changed.
② bag2 is an immutable bag with fixed content (two strings)
③ You can create a bag from another one by excluding some elements.
④ This is the way to create a bag with the same elements of two other bags. If the content of any bag changes, the contents of the resulting bag will also change.
⑤ This is the way to create a bag with contents that can be changed dinamically during the execution of the program. You create an InstanceContent object, which holds all the stuff in the bag. You can add and remove elements from it during program execution.
5.4.1. La bolsa global 全局Loopup
Una de las "bolsas de viaje" más importantes de NetBeans es la bolsa global, conocida en inglés como el "Global Lookup". Es un objeto que contiene todos los servicios declarados en los directorios "META-INF/services" de todos los archivos jar de nuestra aplicación.
Para acceder a la "blosa global" escribimos el siguiente código:
Lookup bolsaGlobal = Lookup.getDefault();
Para almacenar objetos en la "bolsa global" no tenemos más que añadir una entrada en el directorio "META-INF/services". Basta incluir un fichero de texto plano que tenga el nombre de un interfaz, y luego dentro del fichero escribir el nombre de una clase que implemente dicho interfaz. Si no lo tenemos claro podemos acudir a la información en línea sobre el mecanismo estándar para añadir servicios
5.4.2. Otros tipos de bolsas 其他类型的包
A veces necesitamos una bolsa con un único objeto. En este caso podemos hacer uso de una clase muy útil llamada "org.openide.util.Lookups" (fíjense en la "s" al final). Esta clase nos permite construir una bolsa con un objeto, tal que así:
...
Lookup bolsa = Lookups.singleton( miobjeto );
...
O, si queremos hacer una bolsa con varios objetos, podemos usar el método "fixed", tal que así:
...
Lookup bolsa = Lookups.fixed( "Hola", new Integer(3) );
...
También podemos hacer una bolsa que cambie dinámicamente, añadiendo y eliminando objetos a nuestro antojo. Para ello necesitamos un contenedor especial, denominado "InstanceObject" y una bolsa especial de tipo "AbstractLookup". Haríamos lo siguiente:
InstanceContent contenedor = new InstanceContent();
contenedor.add( "Hola" );
contenedor.remove( "Hola" );
contenedor.add( new Integer(3) );
Lookup bolsa = new AbstractLookup( contenedor );
Finalmente podemos hacer también bolsas específicas que modifiquen el contenido de una o más bolsas. Es como meter una bolsa dentro de otra, filtrando, posiblemente, los contenidos. Esta funcionalidad se consigue usando una bolsa especial llamada "ProxyLookup". Así:
Lookup a = ...
Lookup b = ...
Lookup a_y_b = new ProxyLookup( a, b );
5.5. ¿Y para qué vale todo esto? 这一切值什么呢?

Imagínese que diseña una clase con una serie de propiedades (un entero, una cadena, etcétera). Imagínese ahora que, una vez la ha creado y publicado en un API, necesita cambiarla. ¿Qué sucederá con los usuarios de su API? Tendrán que cambiar su código, ¿verdad? ¡Una verdadera lata!
Lo que puede hacer es añadir una bolsa a su objeto, e ir poniendo en la bolsa diferentes propiedades. De este modo se pueden añadir objetos a la bolsa sin cambiar para nada su API. ¡Es como poder modificar las clases en tiempo de ejecución! ¡Es como sacarse un conejo del sombrero!
5.6. Aprender más 了解更多
En esta sección hemos visto por encima la librería de Lookup de NetBeans. Hay muchísimo más. Por ejemplo, ¿sabía que podemos informarnos de cambios en el resultado de un Lookup? ¡Hay listeners que nos permiten hacer justamente eso! ¿sabía que puede construir sus propias bolsas? La verdad es que hay mucho que aprender (y que aprovechar).
Para más información puede consultarse el javadoc de la librería, o el API y, cómo no, las listas de correo de NetBeans.
6. Adding an editor for Scheme files
In this section we'll add an editor for Scheme files to our Scheme IDE. While doing so we will learn how to manage dependencies between modules, and will start modifying the XML Layer file. In order not to make this section too big we'll add syntax highlighting in another section.
6.1. Creating another module for the editor...

I could add the editor for Scheme files inside our existing "Scheme Filetype" module. But I won't do that. As I explained before, building many small modules is much better than building big fat modules: smaller modules give you more flexibility, give you more cohesion, and allow you to enable and disable buggy features easily. The smaller the module the better.
So let's add another module to our SCHEMESUITE Module Suite. Select the "File/New Project" menu in the NetBeans IDE and then choose "NetBeans Plug-in Modules/Module Project".
Let's use SCHEMEEDITOR as the "Project Name" (yes, I like capital letters for these), and let's make sure we're adding the module into our SCHEMESUITE Module Suite.
Once you're done click "Next" and you should be seeing something similar to Figure 22, “Adding a new editor module”. Note , again, that I use the same naming convention as with the previous module: my domain name (net.antonioshome), a common string for all modules in the suite (scheme) and a name for the module (editor).
6.2. NetBeans' delicious EditorKits
Now that we're all set with this brand new module let's add an editor for Scheme files. What we want to do is to add a custom EditorKit (let's call it SchemeEditorKit) and have it associated with our "text/x-scheme" mime type. That's the standard way to do it using the Swing Text API.
But, hold down just a minute: NetBeans includes some delicious EditorKits, which bring lots of cool features to Swing's plain EditorKits. NetBeans EditorKits come in different flavors, with a different set of features. You have the following types of EditorKits: Figure 23, “Types of EditorKits”

That may seem confusing at a first glance, but the fact is that is extremely interesting and powerful! Let's see some cool features of all these EditorKits:
Different packages!
The first thing we observe is that some of the NetBeans Editor Kits live in the "org.netbeans.editor" package. This is so because they can run outside the NetBeans IDE. This is: you can use those as an open-source, standalone, powerful syntax highlighting enabled EditorKits, in your preferred Swing applications. I may post a blog entry on how to do that in the future. So remember that the "BaseKit" and "ExtKit" may be available as separate libraries.
And finally the more specialized EditorKit, the NbEditorKit, is inside an org.netbeans.module.editor package, meaning that it's contained inside the NetBeans Editor module. As we'll see later that means that we'll have to add a dependency to that module if we want to use such an EditorKit.
Line oriented!
The "BaseKit" EditorKit from NetBeans returns a customized version of Swing's Text Document that is line oriented. This makes the BaseKit a very interesting EditorKit for IDEs, because it makes things faster. Furthermore, BaseKit has been around for such a long time that it has been deeply tested. So the BaseKit alone, with line-oriented Documents, is just a great piece of software. It also adds syntax support, so as to allow for syntax highlighting.
Actions!
The "BaseKit" adds a lot of Action to your text-editing capabilities. There're are predefined actions for many editing operations: deleting until the end of the line, from the beginning of the line, enabling macro recording, go to the next word, to the previous one, and many, many others.
Custom UIs!
NetBeans Editor Kits use also a specialized EditorUI that is responsible for visualizing the editor. It also includes customized versions of all sort of specialized Views, that use the Flyweight Pattern to speed up stuff. As a result the NetBeans Editor is a complex, high performance, nicely designed editor that you can include in your Java software. It's so cool that it can include toolbars, popup menus, a margin for line numbers and code folding and even a status bar: a delicious piece of software, indeed.
Of course there's much more inside the NetBeans Editors, but I think this is good enough to give a rough idea of what's hidden in there. And of course nice enough for our Scheme IDE. So let's go back to our goal: build a SchemeEditorKit for Scheme files.
6.3. Building a SchemeEditorKit
Let's get started: let's right-click on our package and let's say we want to add a new Java class, and let's call it SchemeEditorKit.

Let's make this class extend "NbEditorKit" (so that we have all the benefits of BaseKits and ExtKits), and have a "getContentType()" method that returns the text "x/text-scheme", the MIME type of our scheme files. You should be seeing something similar to Figure 24, “SchemeEditorKit.java”.
Note that there's an error marked in red, because the "NbEditorKit" class cannot be found. This is so because we have not added the NbEditorKit class to the set of libraries of our module. The "NbEditorKit" class lives in a Public API inside one of the NetBeans provided modules. We must declare a dependency between our module (the Scheme Editor module) and whatever module owns that class. This is an important idiom while developing with the NetBeans Platform:
-
You need a class that you cannot import, because there's not a dependency between the module you're building and the module where the class resides.
-
You declare a dependency between the module you're building and the module holding the class. You probably want to know which module holds that class. This is done with a NetBeans wizard very easily, as we'll see immediately.
-
Once the dependency is done you can import and use that class (you usually do that pressing Alt+Shift+F, or choosing the "Source/Fix Imports" menu item to fix imports automagically).
All that may seem very complicated, but the fact is that it's a piece of cake! Let's see how to find which module holds the required NbEditorKit and how to add a depencency with it.
6.4. Adding dependencies to other modules
Right-click on the "Scheme Editor" module and select the "Properties" menu item. Then click the "Properties" category. You should be seeing something similar to Figure 25, “No declared dependencies”

As you can see there're two main buttons there:
Add New Library
This adds a new library to our module. Of course this will be a Library Wrapper Module, as we explained a few sections ago. This button is used to add dependencies between our module and third-party, non-NetBeans software. You could use this to wrap a third-party library, such as the SISC Scheme interpreter, for instance. We don't need that now.
Add Dependency
This button adds a dependency between our module and either another module of ours, or a module existing within the NetBeans Platform. This is the one we want to choose.
So we need the second button: the "Add Dependency" button, because we want to find which NetBeans module owns the NbEditorKit class. Let's click on it.

Once you click on it you should have a dialog similar to Figure 26, “Which module owns NbEditorKit?”. There's a "Filter" text field that you can use to find stuff. You can type lots of stuff there. Let's find out which module holds our NbEditorKit class. If you type the class name there ("NbEditorKit") a single module will be selected: the "editor" module. Note that there's a "Description" text there that shows further information about the module. All NetBeans modules in the NetBeans IDE are shown, as well as your own modules in your suite.
Once our "editor" module is selected let's press "OK". This will make our Scheme Editor Module depend on the NetBeans Editor module. That's it! As you can see, adding dependencies to modules is just a piece of cake, isn't it?
Well, not quite. If you try to build the project you'll see that the compiler complains about not finding the "ExtKit" class (that is the super class of NbEditorKit). This is so because, as we explained before, dependencies are not transitive! So, again, we'll have to go find out which module owns "ExtKit". The process is the same as above: Project/Properties/Libraries/Add Dependency, but now looking for the module that owns ExtKit. This is left as an exercise to you. Hint: only one more dependency is needed. (Ok, if you cannot find your way out then look here[1]).

Dependencies are stored explicitly in a file in your project. If you open the "Important Files" folder and then the "Project Metadata" you can see it for yourself. This is an XML file specifying (among other things) what other modules you're dependent on. Note that there're different types of depencencies (compile-dependency and runtime-dependency) and that you can specify the release version and specification version of the modules you depend on. You can see an screenshot of this important file at Figure 27, “Detail of the Project Metadata file”. We'll go deeper into this file afterwards, just in case of need.
6.5. ... and registering our SchemeEditorKit
Once our dependency is set we are able to import the NbEditorKit class and compile our SchemeEditorKit.java file without problems. Remember that Alt+Shift+F in NetBeans performs an automatic import for you.
So we are ready to run our Scheme editor. Or not? Wait a minute. How are we going to register our SchemeEditorKit into the NetBeans Platform? How to tell the NetBeans Platform that we want to use our SchemeEditorKit when opening Scheme files?
Well, of course, by using our layer and inserting it into the NetBeans Platform Sandwich. That easy. In a declarative way. Without a single line of code. Let's do that.
Let's open our sandwich ("Important Files"/"XML Layer"/"in context") and let's try to find out where we should add our layer. There's an "Editors" folder there... and a "text" folder... and lots of file types ("x-java", "x-properties", "x-jsp", "html"...). Yes, I think this should be "Editors/text/x-scheme".
Let's verify we don't get fooled with folder display names vs. real names. I open the properties window and verify that yes, the "Editors" display name corresponds to the "Editors" name. Same for "text". So I assume we should the following set of nested folders: "Editors/text/x-scheme".
If you look under "Editors/text/x-java" (the folder corresponding to the EditorKit used to handle Java files in the NetBeans IDE) you'll see an entry named "instance of JavaKit". This means that there's a living Java object in the layer!!. This is something similar to having some tuna in your sandwich (I mean, you have tomato and lettuce, text files and property files, but the possibility of having Java objects in there is just cool. It's like being able to add some tuna and fancy stuff to your sandwiches, the more the flavors the better the final sandwich ;-) ).
So let's add a plain Java object to our sandwich, a plain Java object of type SchemeEditorKit. Under the "Editors/text/x-scheme" folder.

To add a living Java object in your layer you need a "file" type of entry (of course, entries can be either folders or files, and this is not a folder ;-)) with a special name ending with ".instance". Entries of type "file" with a name that ends in ".instance" represent living Java objects. So we'll be adding a "file" entry named "EditorKit.instance" (a living Java object named "EditorKit", to abbreviate). The "EditorKit" prefix is mandatory and fixed by the NetBeans Editor Module. The NetBeans Editor Module seeks for instances of Java objects named "EditorKit" under the folder corresponding to the mime-type of the file being opened. If you open a "text/x-java" file then the editor module will seek for a living Java object named "EditorKit.instance" under the "Editors/text/x-java" folder; and if you open a "text/x-scheme" file then the editor module will seek for a living Java object named "EditorKit.instance" under the "Editors/text/x-scheme" folder.
After adding our fancy living Java object named "EditorKit", we have to tell the XML layer what sort of object we're adding. That is done with an attribute inside the "file" element. This attribute must be called "instanceClass" (quite reasonable, I think) and it must have a stringValue with the name of the class.
So the result should be something similar to Figure 28, “SchemeEditorKit XML Layer file”. (There're alternative ways to add Java living objects in your XML layer file [2])
Remember that after cooking your XML layer you have to wash your hands. I mean, validate the XML file. Just in case. Right-click on the editor and choose "XML validate". Much better.
6.6. Ready, steady... what!?
So let's run our Scheme Suite with our brand new SchemeEditorKit. This is going to be cool...
... well, not quite. The fact is that our SchemeEditorKit is correctly registered, but when we try to open a Scheme file... we have a white screen!!
Oh, why is that? Well, the fact is that it's because we have not defined a Syntax for our Scheme files, so the NetBeans editor module just doesn't know what to do with all our text, and everything is printed in white on white.
Furthermore, we haven't told the NetBeans Platform which key bindings to use. The platform includes several sets of key bindings. You have the NetBeans default key binding, or the Emacs one or the Eclipse one. We haven't specified that, so we have no key bindings.
And that's why we have a blank screen where you cannot move the cursor around.
So we'll have to add some color to our Scheme files. And specify some key bindings too. But that's just another story, that deserves a section of its own.
6.7. Summary
Although this section was dedicated to building an editor, we ended up having half an editor only, but and a more clear understanding of dependencies and XML layer files. Well, I think it has been worth the deal. After all, understanding how to manage dependencies is indeed important, isn't it? There are lots of good modules in there to depend upon, right? ;-)
So keep tuned for the next section (I'm still cooking it) that will tackle the wonderful world of NetBeans syntax highlighting. That would basically follow the directions of Geertjan's excellent tutorial on syntax highlighting, but with some extra reg-ex topping and some pointers to bleeding edge new ways to do things. Mmmm... Simply delicious!
[1] You'll need to add a dependency with "Editor Library"
[2] You can add a file entry with a name specifying the full class name of your object, using dashes instead of dots. For instance, you could say:
to insert a living object of type "net.antonioshome.netbeans.MyObject".
7. Scheme Editor Options
In the last section we ended up with a SchemeEditorKit that did not work properly. We were missing some key bindings and some syntax highlighting.
In this section we'll add some options to the Scheme editor. We'll set the key bindings, the caret blink rate, the fonts, the number of spaces per tab, a default indentation engine, lots of much more options and even an useless option (just to see how things work). We'll also have to persist those options, so that the user doesn't have to reenter them when he starts again the Scheme IDE.
And, you know what? We'll do all that with a single class, a specially cooked XML file and another entry in our sandwich layer. It's so easy that I'm ashamed I haven't looked into this stuff earlier! It would have saved me lots of time!
7.1. Options and BaseOptions

The NetBeans Platform includes an Options API that handles the so called System Options. These are properties that you set in a module so that the user can modify them easily through the Options Dialog. These options are automatically persisted on disk, so you don't have to worry about storing them yourself. This is something similar the Java Preferences API, but much more powerful.
As we will see, the Options API is so powerful that you can add your custom properties to a Java Bean you're defining, and have all those properties automagically persisted for you. The fact is that the NetBeans Platform uses Java Bean Introspection to seek for those properties.
In fact the NetBeans team has been always concerned about standards, and this introspection mechanism follows the Java Beans Specification. This basically means that you can use BeanInfos to customize how your properties are edited (this is, you could add custom property editors to edit them), or to specify descriptions for those options.
I won't be covering BeanInfos at the moment (I don't think I really need them now). If you think you need them then you should probably go take a look at the Java Editor Options package, the Java Editor Options has a powerful BeanInfo you can learn from.
The NetBeans Editor Module uses the Options API to handle editor-related settings, such as the number of spaces per tab, the caret blink rate, the abbreviations, the font size, the indentation engine to use, the color of the caret, the key bindings, different colors and many, many other settings. It does so using a special class, called "BaseOptions" that is included in the Editor Module.
Of course it's important to associate at least a default set of options to an editor, otherwise you won't be able to work with it (you won't have key bindings, for instance!). That's the problem we were facing in the previous section: our SchemeEditorKit had no options at all (not even default ones) so the NetBeans Platform was confused and didn't know how to properly render our SchemeEditorKit, resulting in an unusable editor.
7.2. Do we need a new module?
In previous sections I suggested that you should be doing different things in different modules. This makes your application much more flexible. But, should we place the options in a new module of its own? Or should we just add the single class inside the Scheme Editor Module?
I could build a separate module just for options (following my self advice of making tiny modules) but, why would anyone want a Scheme Editor Module with a SchemeEditorKit that does not work? Wouldn't it be better to include the Scheme editor options stuff inside the Scheme Editor Module, so that everything works correctly?
Yes. I think it's a better idea. So let's place all the stuff inside the Scheme Editor Module. But let's try to separate it from other classes. Let's store the new classes and files inside the "net.antonioshome.scheme.editor.options" package.
7.3. SchemeEditorOptions
So let's build a new package "net.antonioshome.scheme.editor.options" and let's create a new class, call it SchemeEditorOptions.java, and make it extend the BaseOptions in the NetBeans Editor Module.
As we said before, the "BaseOptions" class is a derivative of the "SystemOptions" class (in the "Options API") that contains predefined options for editors (key bindings, caret blink rate, and many others). Base Options is a Java Bean with properties for editors. It has setters and getters. There's a "setCaretBlinkRate(int)" method, for instance, that sets the caret blink rate. If we wanted to add another property to Since BaseOptions (and SchemeEditorOptions) are JavaBeans, we can add new properties of our liking. And these will be persisted to disk and restored when the Scheme IDE starts up. This is cool!
Just for fun, and to see how things work, I've added a "MyFunnyProperty" to the SchemeEditorOptions class. I don't know yet what sort of options I'll have to add to an Scheme editor, but I now know where I should be storing them!
The "SchemeEditorOptions.java" class, that we have to create, looks something like this:
package net.antonioshome.scheme.editor.options;
import org.netbeans.module.editor.options.BaseOptions;
/**
* SchemeEditorOptions is responsible for handling Scheme options.
* @author $Author: $ Antonio Vieiro (antonio@antonioshome.net)
* @version $Revision: $
*/
public class SchemeEditorOptions extends org.netbeans.modules.editor.options.BaseOptions
{
/** A name for these options */
public static String SCHEME_PREFIX= "scheme"; // NOI18N ①
/** A default constructor */
public SchemeEditorOptions()
{
super( SchemeEditorKit.class, SCHEME_PREFIX ); ②
// Just for fun: modify a property in the base class ;-)
setCaretBlinkRate( 450 );
}
/** A funny property */
private int myFunnyProperty; ③
public void setMyFunnyProperty( int aValue ) ④
{
myFunnyProperty = aValue;
}
public int getMyFunnyProperty() ⑤
{
return myFunnyProperty;
}
/**
* This is used to retrieve display names to
* easy internationalization of options.
*/
protected String getString(String key) ⑥
{
try
{
return NbBundle.getMessage(SchemeEditorOptions.class, key);
}
catch (MissingResourceException e)
{
return super.getString(key);
}
}
}
Let's review what this code does.
① Options are stored on disk in a centralized place. In order to separate options from different modules, each module uses a specific name to differentiate its options from others. That way an editor cannot override by accident options from another editor.
② In the constructor we associate the SchemeEditorKit class with the prefix we have chosen for Scheme options. That way our SchemeEditorKit (that we created in the previous section) will be initialized with all those default options for key bindings, caret blink rates and the such. The "BaseOptions" constructor will associate default key bindings, default carent blink rates, default colors and fonts, and lots of other different options. So we need no extra coding, we have all this bunch of functionality with just a single line of code. Anyway you can set your preferred values of some properties there, too. I've modified the caret blink rate, for instance, to 450 milliseconds. Just for fun ;-).
③④⑤ You can add custom properties of your liking too. These will be persisted by the options subsystem automatically for you. The fact is that NetBeans performs some Java Beans Introspection for you, and detects all the properties you add to your options. These properties will then be persisted and presented to the user in the "Options Dialog", as we'll see later. Java Beans Introspection is a quite common task in NetBeans, and provides a quite powerful mechanism in different modules. Properties can be simple types or complex types of your liking. [3]
⑥ The "getString" method is responsible for returning localized strings for the user to see. The options API will invoke this method to retrieve display names of stuff to be presented to the user in the Advanced Options Dialog. What we do in this method is to use a NbBundle and to ease internationalization. The first argument to the "getMessage" method is a class used to locate a "Bundle.properties" file, which in turn is a resource bundle for internationalization. Note that the NbBundle class is located inside the utilities library, and that you'll have to add a dependency to that.
The Bundle.properties file, that you have to place near the "SchemeEditorOptions.java" file, contains just a single entry used to give a display name to the options. The code looks like this:
# Resource Bundle file for Scheme Editor Options.
OPTIONS_scheme=Scheme Editor Options
The key "OPTIONS_scheme" is fixed by the options module, and is used to identify the set of options for our Scheme Editor (note that the "scheme" part is due to the SCHEME_PREFIX above).
Of course we'll have to tell the NetBeans Platform that we have created this class, and that we want it to be executed so as to get those default options in our EditorKit. We have to register our custom SchemeEditorOptions within the platform. Any idea on how to do it?
No? Really? Think of it again...
Yep. We'll be registering it with... the XML Layer File! Of course! Let's add another layer of options to our sandwich.
7.4. Registering options with the XML Layer File
Registering options with the sandwich file is performed in two steps. First we'll add an entry pointing to an external XML file, and then we'll have to write that XML file in a special format, obeying a special DTD just for options.
This may seem complicated, but it's again a piece of cake once you know what you're doing. Just think of all the hassle we're avoiding (persistence, for instance). Isn't it worth the effort? I think so!

The entry to add to the XML Layer File is a "file" entry named "Settings.settings" (this name is fixed by the platform). The "file" entry has an "url" attribute pointing to our external XML file for options. Since URLs are relative to the location of the XML Layer File, we'll set the value of the "url" attribute to "*options/*SchemeEditorOptions.settings", and will create an empty XML file named "SchemeEditorOptions.settings" under the "net.antonioshome.scheme.editors.options" package.
So to summarize, the XML layer file has a new entry (located under the "Editors/text/x-scheme" folder) that looks like Figure 30, “Registering editor options in the XML Layer”.
The external file ("SchemeEditorOptions.settings") is much more involved than the XML Layer file, and looks like this:
<?xml version="1.0"?>
<!DOCTYPE settings PUBLIC "-//NetBeans//DTD Session settings 1.0//EN"
"http://www.netbeans.org/dtds/sessionsettings-1_0.dtd">
<settings version="1.0">
<module name="net.antonioshome.scheme.editor"/>
<instanceof class="java.io.Externalizable"/>
<instanceof class="org.openide.util.SharedClassObject"/>
<instanceof class="java.beans.beancontext.BeanContextProxy"/>
<instanceof class="java.io.Serializable"/>
<instanceof class="org.openide.options.SystemOption"/>
<instanceof class="org.netbeans.modules.editor.options.OptionSupport"/>
<instanceof class="org.netbeans.modules.editor.options.BaseOptions"/>
<instance class="net.antonioshome.scheme.editor.options.SchemeEditorOptions"/>
</settings>
This "settings" file specifies settings for the module "net.antonioshome.scheme.editor" (see the "module" element at the beginning?). And then it specifies all the class hierarchy until our "net.antonioshome.scheme.editor.SchemeEditorOptions" file. Note that this is a Serializable class (because we will be persisting data from SchemeEditorOptions to disk!)

I assume[4] that specifying the class hierarchy explicitly is needed in order to correctly deserialize the class. After all deserializing the class will require loading classes from different modules and libraries (the libraries containing org.openide.util, and org.openide.options and the editor module and the Scheme editor module). Specifying them explicitly avoids the NetBeans Platform having to load too many modules: the platform will be able to load only those modules required to deserialize our options. This, of course, is better for performance!
Once we've updated our XML Layer file we, of course, have to wash our hands. This is, validate it. Right-click on the editor and select "XML Validate" in the popup menu
And we're almost ready to run our editor. You can run the SCHEMESUITE project now, but you won't yet be able to correctly edit Scheme files. We need another little step: we need to recognize the syntax of Scheme files.
7.5. Using a plain syntax
Since I don't want to make this section too long I think it's better to introduce some plain syntax, and dedicate the whole next section (still on the frying pan ;-)) to syntax highlighting.
A plain syntax just recognices words. And words are printed on black on white. Just like plain text files. That's why it's called plain, after all!.
Adding a plain syntax is just a piece of cake. You'll have to add the following method to the SchemeEditorKit:
public Syntax createSyntax(Document document)
{
return new PlainSyntax();
}
And, of course, add a dependency to the module containing the PlainSyntax class using the steps we talked about earlier at Section 6.4, “Adding dependencies to other modules”. PlainSyntax is useful to have a quick and dirty syntax for editors, or for editors that do not need to have syntax highlighting. Indeed a handy class.
7.6. Summary
In this section we had a snack with NetBeans options for editors, we introduced the XML file for settings and we added a plain syntax for Scheme files. Our editor should be working now, and we should be able to open and save Scheme files.
In the next section we'll add some color to those ugly black-on-white Scheme files, adding special colors for Scheme library procedures and constructs. That's going to be fun all the way long. Keep tuned for some colorful Scheme!
[3] If you have a complex type you'll have to provide a custom PropertyEditor to modify the property (and use a BeanInfo class).
[4] And this is just my assumption, I may be completely wrong on this
8. Colorful editors: The Old, The Good and The Young
So on last section we ended up with a working black-on-white editor. And we wanted to add some color to our Scheme code. In this section we'll take a look at he current syntax highlighting stuff in the NetBeans Platform. While doing so we'll learn about Editor Settings and module installers. Since this is a complex issue I'm afraid I'll split the stuff in two different entries.

8.1. Adding color to editors: The Old, The Good and The Young!
As far as I have seen there are at least three ways to add color to your editors in the NetBeans platform: there is the ugly, old way (the one I will be following here), the standard way (the one explained in the excellent NetBeans Syntax Highlighting Tutorial) and the young one (the one that is currently on the works).
So why all these methods? Well, these different ways to do the same thing show how NetBeans has evolved. The old method is probably not a proper way to do things nowadays (but it has its advantages, as we'll see). The "good way" is a better approach, and it's the current way to add syntax highlighting. And the "young" way is indeed young, still in its infancy, and the NetBeans Team is still polishing it.
The good news is that all these three methods are backwards compatible, so "the old way" to add coloring to text is a subset of "the good way". And "the young" is in turn a superset of the previous one.
Let's give them a quick review, let's understand how they relate to each other and see what the pros and cons of each one are.
The ugly, old way
The old way to add color to your editors is the one I will be following here. I will be doing so because this mechanism requires only the NetBeans Editor Library and, as a consequence, the method allows you to use the same technique in standalone editors. And having a standalone editor with syntax highlighting is something really interesting for me, so I can add it to my Swing applications!!
As we will see, this old way to do things is just a subset of the method described in the NetBeans Syntax Highlighting Module Tutorial ("The Good"). We can always move to "The Good" mechanism by adding some extra Java and XML files.
The good
The good way to add color to your editors in the NetBeans Platform is summarized in the NetBeans Syntax Highligthing Module Tutorial. This is basically the same as the old way, but requires some additional classes and files.
This good way is an evolution over the previous one. The main benefit of this method is that colors can be easily edited by the user using the new Options Dialog. This new Options Dialog presents some sample text to the user (sample text you can define, of course), and allows easy selection of colors for the differents parts of the text. If you are running the NetBeans IDE and choose the "Tools/Options" menu item you'll see what I mean. You have special entries for assigning colors to the editors. This is just cool.
Furthermore, "the good" way allows you to use "color schemes" that represent a combination of colors. NetBeans includes two color schemes: the NetBeans default color scheme and the "City Lights" color scheme (that uses a black background for the editor). The old mechanism does not allow these features, and makes it more difficult for the user to change colors easily.
As you can see the "good mechanism" is much more advanced than the previous one. As a consequence it depends on some more modules, and makes it more difficult to use it on a standalone editor in a Swing application.

So I will follow the old way, and I may add an extra module to "upgrade" the old mechanism into the new one.
The young
The new way to assign colors to your editors is to use some sort of grammar files, using the Lexer Module. So you can add colors to your favourite languages much more easily. This module has been added to NetBeans CVS Trunk as of 2006-10-04, after passing an exhaustive API review (remember I told you that NetBeans Team was very strict about APIs?). Although this mechanism has been added recently to NetBeans CVS Trunk, the fact is that it has been around for quite a long time. You can see examples (using an old version of the Lexer Module) at the Coyote Project.
The lexer module makes things easier for you, because you can define syntax coloring more easily using text files. Furthermore, it makes it easier to work with files that require different syntaxes (such as JSP files, that require an HTML syntax and a Java syntax). It also makes things even faster, and requires less parsing and overhead than the previous mechanisms.
The lexer module API is still considered unstable, so you are still on time to suggest changes. It's a great time to try it out, experiment with it and give feedback to the NetBeans Team.
So now that we have a high-level overview of these mechanisms, let's go take another high-level overview of what we have to do. Let's review the main classes needed to add coloring to our Scheme editor.
8.2. The old way: overview

The class diagram at Figure 34, “Classes required to colorify our Scheme editor” shows the classes that we need. Note: if you want to see source code for these, I recommend you visiting the NetBeans Syntax Highlighting Tutorial, many links below point to that tutorial.
SchemeTokenContext extends TokenContext
TokenContext objects are responsible for defining the types of tokens that appear in the text. For instance, when parsing Scheme documents I think I'll need the following tokens: whitespace, scheme standard procedures, scheme constructs, constants (strings and numbers), variables and comments (and probably some others).
Those tokens are represented by special Java classes called "TokenIDs". These "TokenIDs" contain an integer (a sort of primary key) and a display name (that is also internationalized). Display names use a prefix (such as "scheme-" or "mf-" in the tutorial) to distinguish between different languages, avoiding namespace polution.
You can see some source code from the NetBeans Syntax Highlighting Tutorial. As you can see this is an easy class: you just define what types of tokens you want in your language and create BaseTokenIDs for those.
SchemeTokenColoringInitializer extends TokenColoringInitializer
TokenColoringInitializers are responsible for assigning colors to tokens (to TokenIDs). Both for on-screen visualization and for printing output as well.
In the NetBeans Syntax Highlighting Tutorial you can see this as an inner class inside the ManifestSettingsInitializer. Source code is here.
SchemeSettingsInitializer extends SettingsInitializer
SettingsInitializers are responsible for populating options with appropriate settings. These are useful if you have complex set of options, such as those defining fonts and colors.
Building a custom SettingsInitializer is not that difficult. You can use the ManifestSettingsInitializer and use it as a template for your own stuff. That's what I've done with my SchemeSettingsInitializer.
SchemeSyntax extends Syntax
Syntax objects are responsible for recognizing text as the user types it, returning appropriate TokenIDs (those defined in the associated TokenContext).
Syntax objects are possibly the most difficult thing to build when adding colors to your editor, because there are very tough non-functional requirements for them: they must run fast and generate as little garbage as possible. Because they are run whenever the user modifies the document.
The "old way" and the "good way" to do things use state machines to keep track of the token the user is typing. That's efficient (both in time and space) and is probably the best solution around. The problem is that building them is somewhat difficult.
The "new way" to do things does this operation automatically, using language description files that are easier to build, so you don't have to build the Syntax object by hand, using state machines. I may consider using the new way as soon as it stabilizes.
You declare your custom Syntax object in the Editor Kits. So, for instance, in our SchemeEditorKit we have to return our custom SchemeSyntax, like this:
public class SchemeEditorKit extends NbEditorKit
{
public SchemeEditorKit()
{
super();
}
public String getContentType()
{
return "text/x-scheme"; // NOI18N
}
public Syntax createSyntax(Document document)
{
return new SchemeSyntax();
}
}
So, to summarize: adding colors to our Scheme text files works like this: you have to build your custom Syntax object, that translates text to TokenIDs (defined in your TokenContext). Those TokenIDs are in turn translated to colors using the TokenColoringInitializer, which is in turn inserted into the options dialog using a SettingsInitializer.
Not very difficult, but, who invokes the "SettingsInitializer"? We'd like it to be executed when our editor module is initialized, right?
But, how do we execute code when a module is initialized?
That's such an important thing that I've moved that to the next section below.
8.3. Executing Java code on module initialization
As we said before, executing code on module initialization is a problem, because code execution is time consuming, and we don't want all the modules to consume time on startup. That would make the whole application startup slow.
But in this case we'll have to add a module installer that inserts our custom editor settings (our custom colors) into the editor options.
But, wait a moment! Why can't we do this with the XML Layer file? Isn't that supposed to be used to register stuff into the NetBeans Platform based application? Why shall we do this by hand and not by adding some more tomato layers to our sandwich?
I am not sure about this, but I assume we have to do things by hand because the editor Settings stuff belongs to the NetBeans Editor Library, and this is a library that can be used outside NetBeans, in standalone Java applications, where no XML Layers exist. And that's why we need a module installer to populate our coloring settings inside our options.
8.3.1. Creating a Module installer
Each NetBeans module may contain a "module installer". This a plain Java class that extends ModuleInstall[5].
The NetBeans IDE contains a wizard that eases creating these Module Installers. The wizard creates this custom class and registers it in the XML Layer file automatically for you.
To start this wizard you choose "File/New..." in the main menu and then you select the "Module Installer" option under the "NetBeans Module Development" section, as explained graphically at Figure 35, “Creating a Module Installer, step 1”
After that you just click "Next" and "Finish" (as you can see in Figure 36, “Creating a Module Installer, step 2”).

Once created you can override different methods of the "ModuleInstall" super class: restored(), uninstalled(), close(), closing() and validate(). Let's take a quick look at these methods.
restored()
The "restored()" method is the one you'll probably use more often. The NetBeans Platform will invoke the "restored()" method during application startup. It is important to note that this method sums up into application startup time[6], so you must do things as quickly as possible. It is important to note as well that the whole application has not been yet initialized, so you are limited on what you can do. This method is the one we'll be using to inject our editor color settings.
uninstalled()
The "uninstalled()" method will be invoked by the NetBeans Platform when your module is deactivated (removed) from the running application. We won't be using this, because all the settings we're adding are not permanent.
closing()
The "closing()" method is invoked on your custom ModuleInstall when NetBeans is about to close. This gives you a chance to check if everything is ok to close. You can stop the close operation by returning "false" from this method. This is a good place to check if all your stuff is saved, and things like that (note that the NetBeans Platform takes care of unsaved buffers in editors for you, though).
close()
The "close()" method is invoked on your custom ModuleInstall when the application is being closed because all modules have returned "true" from the "closing()" method.
validate()
Finally the "validate()" method is also invoked during startup (so the application may not be initialized yet). This method allows you to verify that everything is ready for you to run. If you develop commercial applications on top of the NetBeans Platform you can use this method to check for licenses, for instance.
And that's basically it! Inserting our SchemeSettingsInitializer (which in turn populates colors with our SchemeTokenColoringInitializer) may be done in the restored() method, like this:
package net.antonioshome.scheme.editor;
import net.antonioshome.scheme.editor.syntax.SchemeSettingsInitializer;
import org.netbeans.editor.Settings;
import org.openide.modules.ModuleInstall;
public class Installer extends ModuleInstall
{
public void restored()
{
Settings.addInitializer( new SchemeSettingsInitializer() );
}
}
Before finishing this section let me remind you that the good way to add colors to your NetBeans editors is explained in the NetBeans Syntax Highlighting Tutorial. Following that tutorial is probably your best option: remember that (since the old way is a subset of it) you'll also be doing things "the old way".
On the next section (on the works) I'll take a look at the "Syntax" object, and explain how I've defined it for the Scheme language.
[5] A plain Java class that can be instantiated like a JavaBean, this is, that has a public void constructor
[6] I think the NetBeans Team is looking at multithreaded application startup, so things may be faster in the future
9. Adding Syntax Support

As we saw in the previous section, there are different ways to add syntax highlighting to NetBeans. The "old" and "good" ways to do things required a Syntax object, responsible for tokenizing text. The young way (the lexer module) eases building such objects (and provides some other cool features).
In this section we'll take a look at Syntax objects. When the lexer module is stabilized I'll add a new section here about it.
9.1. Syntax - non functional requirements
The Syntax class has been around since 1999. At that time Java 2 had just been released. At that time microprocessors were somewhat slow (remember those Pentium II?), and so were the Java Virtual Machines (and Swing!). In 1999 the performance of Java based applications was a real issue.
Existing garbage collectors were not as fast as they are nowadays either[7], so memory consumption was also a concern.
So the design of the Syntax highlighting support in NetBeans was influenced by these tight constraints: it should be both time and space efficient. It should run fast, and it should consume as little memory as possible. As a penalty, defining a custom Syntax object is a little bit complex, and requires careful hand-coding.
This section is about building custom Syntax objects, that transform text into tokens.[8]
9.2. Building a custom syntax object
Let's start by creating our custom Syntax class, responsible for transforming text into TokenIDs.
9.2.1. SchemeSyntax, step I: extends Syntax
The very first step to build a custom Syntax is (apart of having ready all the classes we talked about in the previous section, such as SettingsInitializers and TokenContexts) to extend the Syntax class, which is a little bit tricky.
Extending the Syntax class requires creating a public void constructor that updates a superclass variable (and this is the tricky part), and overriding the protected "parseToken()" method that translates text into tokens. The basic skeleton for building our custom Syntax object looks then like this:
public class SchemeSyntax extends Syntax
{
public SchemeSyntax()
{
// The tricky part!
tokenContextPath = SchemeTokenContext.contextPath;
}
// @Override
protected TokenID parseToken()
{
// Some magic here!
return null;
}
}
9.2.2. SchemeSyntax, step II: building a parseToken
The editor module infrastructure will make calls to our overriden "parseToken()" method for us, automatically. And it will be making calls to that method until you analyze the whole text buffer.
And what's the text buffer we have to scan, you ask? Well, that's stored in an internal protected variable in the Syntax class. In fact we have some other juicy variables there. Let's take a look at what these variables mean:
buffer
The buffer variable is the array of chars containing the text to be parsed. Note that we don't have to scan the whole array, but just a part of it. The editor infrastructure is responsible for telling us what part of the buffer we have to scan (and it performs some magic there so that we don't have to scan the whole buffer all the time!).
The part of the buffer we have to scan is stored as a set of offset and length integer variables. Let's review those:
offset (and stopOffset)
The offset variable is an integer containing the current offset inside the buffer. So "buffer[offset]" is always the character we're currently looking at.
The stopOffset variable is another integer containing the maximum offset inside the buffer that we have to check. This is so because we don't always have to parse the whole file, sometimes we only have to check a part of it. The editor module keeps track of what parts of the file may have changed, and asks us to analyze the text between offset and stopOffset.
We are responsible for advancing "offset" until we reach "stopOffset". That's why the "parseToken()" usually has a loop like this:
protected TokenID parseToken()
{
while( offset < stopOffset )
{
char currentChar = buffer[offset];
if ( this is a whole token )
return anAppropriateTokenID;
else
offset ++;
}
return null;
}
lastBuffer
The lastBuffer variable is a boolean indicating if this is our last chance to process the buffer. If set to true then we should return whatever token we're currently parsing, even though we haven't finished yet.
Detecting the end of the buffer is important, and this is usually done after the loop above, like this:
protected TokenID parseToken()
{
while( offset < stopOffset )
{
char currentChar = buffer[offset];
if ( this is a whole token )
return anAppropriateTokenID;
else
offset ++;
}
if ( lastBuffer )
{
// We may return an appropriate token
// and reset internal state
}
return null;
}
Most NetBeans custom Syntax objects use the structure above to perform the lexical analysis of text. You may want to go take a look at the SQLSyntax, the JavaSyntax or at the NetBeans Syntax Highlighting Tutorial Syntax Example.
state
The state variable is an integer containing the current state of our syntax object.

States allow you to react in different ways to the same character. Of course! Imagine you're analyzing a piece of Java code, you'll react differently to the slash "/" character if it's the first time you see it (like in " 1 / 2") or if you're seeing it immediately after a previous slash character (like in " // Comment ")!.
So Syntax objects work effectively as state machines: for each iteration on the loop (for each character in the text buffer) the token to be returned depends on the character itself and your current internal state. Figure Figure 38, “Sample states in JSON syntax” explains graphically how internal states allow you to know what part of a syntax branch you are analyzing.
tokenOffset
The tokenOffset variable is an integer that represents the start of the current token. Whenever you return a token, the Syntax object keeps track of the offset, and stores it in the "tokenOffset" variable. This is an interesting variable, because you can know the whole text you're currently analyzing by using something like:
String currentToken = new String( buffer, tokenOffset, offset - tokenOffset );
This is what the SQLSyntax, does: it creates temporary Strings with the token currently under analysis, and then it compares that String against a list of keywords. This is an easy way to colorize your text: you basically create three categories of tokens: punctuation, whitespace and text. And then you compare the text with a predefined set of keywords.
9.2.3. Syntax examples
So that's it. Building a custom Syntax object is not that difficult after all: it requires some some attention.
If you want to see real-life examples of custom Syntax objects you may want to take a look at NetBeans' SQLSyntax, the JavaSyntax or at the NetBeans Syntax Highlighting Tutorial Syntax Example.
But, hold down just a moment, there're some juicy tricks you may use to ease building custom syntax objects!!
9.3. Syntax tricks
Since building custom Syntax objects seems somewhat involved let's see some basic tricks to ease things.
9.3.1. Using regular expressions
If you take a detailed look at SQLSyntax you'll see a helper method that recognizes keywords. This helper method creates a new String from the text buffer (using "new String") and that then compares that String against a constant list of SQL keywords.
Of course they're creating new things, so this is not as space-efficient at the JavaSyntax, for instance. Anyway the current garbage-collection technology in recent JVMs has improved so much that creating these short-lived objects is very, very efficient nowadays.
In fact you can even create more interesting short-lived objects: you can create "Matchers" and use regular expressions to match keywords. As you probably know, regular expressions are strongly related to finite state authomata, and so may help us build our custom Syntax state machine. You could, for instance, define the following Pattern that is used to detect Scheme constructs:
private static Pattern CONSTRUCT = Pattern.compile("and|begin|case|cond" +
"|define|define-syntax|delay|do|else|if|lambda|let|let\*|letrec" +
"|letrec-syntax|let-syntax|or|quasiquote|set!|syntax-rules" );
And then use a helper function to detect if a part of the buffer is a Scheme construct or not, like this:
public boolean isConstruct()
{
SegmentCharSequence chars =
new SegmentCharSequence( buffer, tokenOffset, offset - tokenOffset );
return CONSTRUCT.matcher( chars ).matches();
}
And we would only be creating a lightweight "SegmentCharSequence"[9] and a Matcher object per iteration. Again note we're trading space-efficiency by ease of development. And that seems fair to me.
Using regular expressions is most handy if you want to parse complex tokens, such as Scheme numbers. Scheme number syntax is somewhat involved, because you have rational numbers, complex numbers, and exact numbers, for instance. Choosing your regular expressions wisely may boost your productivity when building custom syntax objects.
Remember, again, that if you want to do things really efficiently then you may want to experiment with the lexer module: the new way to do syntax highlighting on top of NetBeans.
9.3.2. Syntax unit testing
The second trick I suggest for building custom Syntax objects is to fully exploit unit testing. Building unit tests in the NetBeans IDE is just a piece of cake (just right-click on your custom Syntax.java and choose Tools/Create unit tests), and building unit-tests for your syntax is not that difficult either.
The NetBeans Syntax Highlighting Module Tutorial contains a good example for building your Syntax unit tests.
9.4. Multi syntaxes
Java Server Pages can contain HTML code and/or Java code. Web pages contain both HTML and JavaScript code. These type of files, that include different languages, require the use of a MultiSyntax object. I won't be covering them here, though.
One of the objectives of the lexer module (the "young" way to do things) is to ease building syntax support for text files that (as in the JSP case) require different syntaxes. So if you need one of these I suggest you experimenting with the lexer module.
During the last weeks there has been some interesting movement in this new way of doing things. Geertjan has been talking about this new mechanism in his blog. If you find that building syntaxes "the old way" is too complex for you then you may want to explore this new, fancy API. I may cover it in the future, when it is considered more stable.
Meanwhile I will keep on using the old API. I may be interested in building standalone editors that use the NetBeans Editor API, like this small Scheme Editor Pane that I can use in small Swing Applications. I'll talk about those standalone editors either in my blog, or in a new section. Keep tuned for that.
[7] the guys at Sun Labs have been quite busy during these last 7 years!
[8] Note that Syntax objects work basically as incremental lexers, since they detect changes in the document and process only the part of the buffer that is affected. Normal lexers (such as JFlex) scan the whole buffer instead.
[9] SegmentCharSequence is both a CharSequence and a Segment.
public class SegmentCharSequence extends Segment
implements CharSequence
{
/**
* Creates a new instance of SegmentCharSequence
*/
public SegmentCharSequence( char[] buffer, int startOffset, int length )
{
super( buffer, startOffset, length );
}
public char charAt(int index)
{
if ( index < 0 || index > count )
throw new StringIndexOutOfBoundsException( index );
return array[ offset + index ];
}
public CharSequence subSequence(int start, int end)
{
if ( start < 0 || end > count || start > end )
throw new StringIndexOutOfBoundsException( " start " + start + " end " + end );
return new SegmentCharSequence( array, offset + start, end-start );
}
public int length()
{
return count;
}
}
Note that Segments will be CharSequences in Java 6
10. Wrapping Scheme into our IDE (Library Wrappers)

So we have a working editor for Scheme files now. Now we want to be able to interpret and run that Scheme source code.
To do that we need to embed our favourite Scheme interpreter into our Scheme IDE. There are different Scheme interpreters that run on top of the JVM (JScheme, Kawa, Jaja, Skij and SISC, and possibly many others). I'll talk about the differences between these in a future entry (there's an outdated comparison in this MIT Thesis by Brian D. Carlstrom, with a description on how to embed Scheme into Java, in case you're interested in these topics).
I must admit I haven't used many of those: SISC is good enough for my needs (furthermore, I want to explore SISCweb in the future, to give web continuations a go). So let's see how to embed SISC into our Scheme IDE. Later on I may want to add different Scheme runtimes into the IDE, but let's keep it small at the moment.
To embed an external library into a NetBeans based application we must understand "Library Wrappers". So let's take a look at them first.
10.1. Library Wrappers
Library Wrappers are NetBeans modules that contain an external library.
Since Library Wrappers are NetBeans modules, you have a well defined Public API. As we'll see in a minute, when you define a Library Wrapper, the NetBeans IDE automatically builds a Public API that contains all classes in the library.
And you have versions, too. Your own versions, that you define when building your Library Wrapper. These "Library Wrapper versions" are independent of the library being wrapped (because these versions correspond to the wrapper, and not to the library).
Finally note that Library Wrappers are designed to contain libraries, and not projects. What I mean is that a library is something that rarely changes (projects change more often). That's why Library Wrappers do not work well if you change the library after building them. We'll also see later on how to handle these cases.
10.2. Getting started: wrapping SISC

So let's get started with Library Wrappers. Let's build a Library Wrapper around SISC.
10.2.1. Download SISC
Oh, well. Before building a Library Wrapper we need a library! So let's download SISC first, and extract the contents somewhere in our hard disk.
10.2.2. Create a new Library Wrapper

You build a Library Wrapper Module by selecting "File/New..." in the menu, and then selecting the "NetBeans Plug-In Modules" category and the "Library Wrapper Module Project" option (see Figure 40, “File/New... Library Wrapper”).
The next step asks us to select the library we want to wrap. Note that you can select multiple jar files and not just only one (I was confused by this when I first built a Library Wrapper), as can be seen Figure 41, “Selecting the jar files to wrap”).
You can also specify a license for the library. The SISC Scheme interpreter is released both under the Mozilla Public License 1.1 (quite similar to the CDDL) and under the GPL 2.0 license. SISC includes its license in the "COPYING" file, so just click the "Browse..." button and select it.
Select all jar files in your Library WrapperRemember that you can select multiple jar files when building a library wrapper module.
The third step in the wizard allows you to enter the project name and location. Remember to add the module to the Scheme module suite we're building.

The fourth and last step in the wizard asks for a code base name for the module. As usual this is a unique name for the module. I follow a convention similar to package names for this name. I enter my domain name (net.antonioshome) and then a name for the application I'm building (scheme) and finally a name for the module (sisc), so I have "net.antonioshome.scheme.sisc" as my code base name.
See Figure 42, “Setting the codename” for details.
10.2.3. Library Public APIs
Now that we have built our Library Wrapper module let's go take a look at it. The very first you may notice is that NetBeans has automagically generated a Public API for our library. You can take a look at this public API by right-clicking on the Library Module and selecting the "Properties" menu item in the popup menu. If you then select the "API Versioning" node you should see something similar to Figure 43, “The Public API of our library”.
The fact is that, NetBeans scans all the jar files in the library and detects the Java packages there, and then marks all of them as public.

This opens new possibilities to us. We can select a small set of packages in the library, and mark only those as public, so that the rest of modules in our application can only interact with those packages.
We could, for instance, mark the "sisc.boot" package as private, so that no other modules could access the classes under "sisc.boot".
This feature has deep consequences in the maintainability of our applications, allowing us to manage dependencies between libraries and modules in a much more powerful way. That's one of the main reasons why I like the NetBeans Platform as a way to build complex applications: you can impose big restrictions on dependencies, which is of main importance when building applications with different development teams, for instance.
So, to summarize: Library Wrappers allow us to define which parts of a library are public, giving us a powerful tool to handle dependencies in our applications.
10.2.4. Managing change
So what happens if we want to change (or update) the jar files in our library? The NetBeans IDE doesn't currently support this operation (well, after all libraries are not expected to change, right?), so we'll have to do it ourselves (or wait until this issue is solved).
I can think of different ways to have our jar files updated. Let's see them:
The first way is, of course, to delete the Library Wrapper module and rebuild it with the same code base name. This is somewhat tedious, but it's probably the safest way to do it.

If you haven't changed the packages in the jar files you can try to rewrite the old ones. When you build the Library Wrapper, NetBeans stores the jar files under the "releases/modules/ext" directory (see Figure 44, “Jar file location”). Of course you can modify the "build.xml" file to have the files automatically overwritten for you.
Finally you may want to use the versions in your Library Wrapper and create different LibraryWrappers, with different versions each, and make a dependency with your preferred version.
10.2.5. Beloved warnings!
After creating the Library Wrapper for SISC you may want, of course, to build it.
And if you do so you'll notice... warnings! (see Figure 45, “Beloved warnings!”)

How is that possible? How is it possible that we have warnings after just creating our Library Wrapper?
Well, the fact is that NetBeans is doing quite interesting things when building our module. It's "verifying the class linkage". What this actually means is that NetBeans scans the class files of our library and looks for unresolved dependencies with other libraries. This is cool because it allows you to quickly see what other libraries you may need.
In our case, NetBeans is informing us that the SISC libraries (well, exactly the sisc.tests.TestR5RS, sisc.tests.UtilTest and sisc.tests.AllTests) require the JUnit library.
We know that those libraries are only required to build SISC unit tests (but are not required to run SISC), so we may dismiss those warnings.
I think this feature of Library Wrappers is very interesting. The fact is that I find it difficult to handle dependencies myself. You know, people tend to use lots of libraries in their software, and it's difficult to see if you have all the required jar files or not. Having NetBeans make that check for you saves lots of time!
Beloved warningsNetBeans scans the class files seeking for unresolved dependencies. This allows you to quickly see if you need some extra libraries or not, and helps you solve those problems quickly.
10.2.6. Native librariers
I haven't yet added native libraries to a NetBeans based application, but it seems this is somewhat tricky. I will have to investigate this thread in the future (well, just in case I ever use a native library! ;-) ).
If you're delivering native libraries with JNLP you may be interested in reading this interesting blog entry by Alan Burlinson about using NetBeans, native libraries, JNLP and the new compression format (pack200) with an Apache server (I also have another entry on using JNLP and pack200 with Apache).
10.2.7. Further reading
The NetBeans Developer FAQ has an interesting entry explaining when to use Library Wrapper (you can also bundle your jars inside your module). This is a good read if you're interested in using Library Wrappers in your applications.
In the next section we'll start invoking SISC and running our first Scheme code. Keep tuned for that, we'll see how to asynchronously invoke things... without SwingWorkers!
11. Invoking Scheme I (creating a Public API)

In the last section we added the SISC Scheme interpreter libraries to our NetBeans Platform based Scheme IDE.
In this section we'll see how to invoke the SISC interpreter. We will define a generic interpreter interface (publishing our first API), and in the next section we'll see how to actually implement it. By doing so we'll learn about NetBeans Platform's Lookup system (the best thing after sliced bread), NetBeans threading (Oh, my! I should have learned about this before!) and the Output Window (the Console).
And, of course, we'll be having fun all the way through. Let's go!
Let's get started.
11.1. Yet another module? No, sir: it's TWO more modules
I think I'll add another module into the Scheme Module Suite. I like making modules responsable for very specific things. We have now a module for recognizing Scheme file types, another module that adds editing capabilities and another module that wraps the SISC library. This new module will be responsible for evaluating Scheme expressions using the SISC Scheme Intepreter (using the SISC Library Wrapper).
But, hold down just a minute. What about if we want to change the current interpreter and use, say, JScheme or guile instead of SISC? Shall we go and change everything? That wouldn't be too modular, would it?
If we were using Java then this could be done easily: we would define a generic interpreter interface and, aftewards, define different implementations, allowing people to change implementations easily without the rest of classes noticing, using a Abstract Factory Pattern.

But can we do this with the NetBeans Platform? And if so, is this difficult to do?
The answer is that it is extremely easy to do, and that the solution relies on the Service Provider mechanism defined in the Jar File Specification (yes, I told you that the NetBeans Community loves following standards) and in the NetBeans Platform Lookup technology.
So instead of creating a single module responsible for invoking the SISC Scheme Interpreter we will be creating two modules: a generic module that defines what a Scheme interpreter looks like, defining a Public API (something similar to a java interface) and another that contains the actual SISC interpreter, the implementation of the interface.
To clarify the current structure of our Scheme Module Suite I've created a sort of UML package diagram (but with modules, not packages) in Figure 47, “An overview of the current modules”.
But how many modules is this guy creating?You may be thinking that I add too many modules, and developing with the NetBeans Platform makes you build tons and tons of modules. Well, the fact is that this is a Good Thing. Having modules have single responsibilities follows the DeMarco's Single Responsibility Principle.
11.2. The Scheme Interpreter Module
So let's create this Scheme Interpreter Module, responsible for defining a public API that we'll use to evaluate Scheme expressions.
Creating a module is so easy that I won't repeat all the steps here (but see Section 6.1, “Creating another module for the editor...” if you need help on creating modules).
I will call this the "Scheme Interpreter" module and I'll specify a code base name of "net.antonioshome.scheme.interpreter": "net.antonioshome" (my domain) + ".scheme" (the project) + ".interpreter" (the module). Yes, I'm following the conventions that I used in previous sections.
Once the module is created let's see what this generic Scheme API should look like, and let's then make it public.
11.2.1. Designing a generic Scheme API
So let's define an API for evaluating Scheme expressions. [10] This API should be as generic as possible (so that we can plug-in different Scheme interpreters afterwards) and, of course, should have no dependencies with the actual implementation.
Let's review some requirements first, so as to define a good API.
An asynchronous API
The very first requirement for our API is that it is asynchronous, so that we can schedule Scheme expressions for evaluation in a worker thread. This will serve us for learning how to do threading with the NetBeans Platform (which is both easy and powerful, as we'll see later on).
So the Scheme expressions will be evaluated in worker thread. Cute. But we need to know what the result of the evaluation is, so we'll need to develop some sort of callback mechanism, that informs us what the result of the evaluation is (and what the errors are, if any).
Evaluating Strings, Files and URLs
We'll also need to keep it simple. I'd like to evaluate simple expressions (stored as simple Strings) and to evaluate files containing Scheme source code. So we'll need to methods: one for evaluating Strings and other for evaluating files.
But what if our Scheme source code is stored somewhere else but on a file? What about if our Scheme source code is stored in a web server miles away?
Mmmm. Maybe it's a better idea to add a method for evaluating Readers (after all a new StringReader( aString ) builds a Reader from a String) and another for evaluating Files (setting the current working directory to the directory where the file is stored). That way we'll be able to evaluate both stuff we read from a network connection and stuff stored in our local filesystem.
What about environments?
I'd also like to evaluate an expression and, later on, evaluate another in the same environment. So if I evaluate a "(define a 10)" expression and later on I evaluate a "(display a)" expression (in another thread, possibly), the second one refers to the value of "a" defined in the prior expression.
But to make things more complicated, I won't introduce environments now, but later on.
Yes, this is not a typo! Not introducing them will make things more complicated.
Why, you ask?
Well, think of it before reading any further.
Ready?
By introducing environments later on I will be changing a Public API. And that's asking for trouble, because I will be forcing the rest of modules to adapt to my changes. I will be forced to change all modules implementing the "Scheme Interpreter" interface!
And that's the reason why making things simpler now is making things harder later: if you define a Public API think twice all the use cases. After all you don't want to propagate changes in lots of modules, right?
Think twice before defining a Public API!If you change a Public API you'll have to propagate that change all over the place, to other modules using it. That's why the NetBeans Community has specific processes for API Reviews, and builds use cases for those Public APIs. Making sure a Public API is solid and that it covers all possible use cases is saving time (and money) in the future.
11.2.2. One single interface to rule them all
So to fullfil all those requirements I propose the following API for invoking any Scheme interpreter I can think of:
public interface SchemeInterpreter
{
public String getName();
public void eval( SchemeCallback aCallback, java.io.Reader someExpressions );
public void eval( SchemeCallback aCallback, java.io.File aFile );
public interface SchemeCallback
{
public void onSuccess( String aResultingExpression );
public void onFailure( String anErrorMessage );
}
}
And this will be our Public API for Scheme Interpreters. I've added a "getName()" method to return the name of the interpreter. All the rest should be obvious: two methods for evaluating expressions in Strings and Readers; and a callback interface with two methods: one to be invoked when the expression is evaluated correctly, and another one invoked when the expression generates an error.
And, of course, we should add some more Javadoc (since this is a Public API). Public APIs are Public, and must have good Javadoc (not included for clarity).
Now that our generic Scheme Interpreter interface is ready let's see how to make it public.
11.3. Making our interface public

So we add the SchemeInterpreter interface to our module. To make the API Public we select the module (in the Projects folder), right click on it and choose Properties in the popup menu. The Properties dialog pops up.
Finally we select "API versioning" option on the left of the dialog. A list of all packages in our module is presented to us in the "Public Packages" list. We select ours (net.antonioshome.scheme.interpreter) and click on it to make it public.
I like setting a major release version (and an implementation version) whenever I define a Public API. This way I may be able to make changes in the Public API (which is painful) in case of need.
11.3.1. Next stop: implementation
Once our Scheme Interpreter Public API is ready we are ready to start building an implementation of it (using SISC).
Of course we'll have to integrate the implementation with the SISC Library Wrapper, and we'll have also to see how to do threading (and show progress) using the NetBeans Platform. Keep tuned for that.
[10] The NetBeans Community has special procedures for defining new APIs (that include some formal review processes, for instance), but I won't be following them here. After all this whole thing is just an experiment and we won't cause any harm to the rest of the Community ;-)
12. Noodle Threads (threading, progress, console)

In the last section we defined a generic Scheme interpreter API, and made it public.
We need to implement this generic Scheme Interpreter API using a Scheme interpreter (such as SISC). But before doing so, we need to learn how to do basic things with the NetBeans Platform.
We need to learn how to run a task in background (and how to cancel it), and how to show progress to the user while the task runs. And, of course, how to print out the results of those tasks in the Output Window. With those basic idioms we may start cooking some more complex recipes, such as using our favourite Scheme interpreter.
So let's get some threads chopped.
12.1. Scheduling Threads for Execution
You can schedule Threads for execution as you always have done. Of course. There's nothing new under the sun here. You just create a Thread and you "start()" it. And you're all set.
But the NetBeans Platform contains some other mechanisms for scheduling threads. The first is the so called "RequestProcessor" class, and the second is the "Progress UI API", used to show progress of your tasks to the user. Let's see how easy is to use them (and again let me complain of not having studied all this before).
12.1.1. Threading with the RequestProcessor
The RequestProcessor (included in the Utilities API) has been around probably before 2000. So it's probably seven or eight years old now.
Eight years seems to me as sound. I mean, if a piece of software has been around during almost eight years (being used daily, by a lot of people, and with lots of eyes looking for issues and bugs and improvements) then I think that piece of software must be solid as rock, right?
RequestProcessors are roughly equivalent to Java Executors and Java Executor Services, this is, they're responsible for scheduling Runnables for execution in a set of threads.
Using a RequestProcessor is extremely simple. You may use the default RequestProcessor (a sort of default thread pool) to post your Runnables, like this:
Runnable myRunnable = ...
RequestProcessor.Task myTask = RequestProcessor.getDefault().post( myRunnable );
And your task is automatically scheduled for execution in a worker thread. That simple.
Note that you get a RequestProcessor.Task in turn, which is roughly equivalent to a Java FutureTask: an object you can use to cancel the task, for instance.
You can also create your own RequestProcessor with a predefined number of threads. That's probably a good idea if you don't know how many task user may spawn.
So that's all we wanted to know about RequestProcessors. As we've seen they're quite powerful (and quite simple to use as well).
I recommend you to review RequestProcessor's javadoc, just to see for yourself what you can do with this nice piece of (reusable) code.
Interrupting tasks
To interrupt a task you just use the RequestProcessor.Task handle and invoke "cancel()" on it. And you may be able to interrupt it.
May interrupt it? How so, you ask?

Well, the fact is that not all Java threads are really interruptible. I mean, you can "interrupt()" all Java threads, but not all of them will be really interrupted.
If you thread performs I/O operations (such as reading a file, or reading data through a JDBC connection) then your thread may be interrupted. But if your task does some heavy maths (or other computations without I/O operations) then your thread may not be interruptible. (I blogged about this earlier). This is so because all I/O operations invoke the "Thread.interrupted()" method periodically, and if the method returns true then they stop operation.[11]
But if you just burn your CPU with a long math computation and you don't check if "Thread.interrupted()" for yourself, then your task may be really uninterruptible. It will keep going even you invoke RequestProcessor.Task on it.
So if you want to make your tasks interruptible remember to check for "Thread.interrupted()" periodically. Just in case.
12.1.2. Showing progress
Of course we want to show progress of our task to our users. I mean, scheduling things for execution and not telling the user is somewhat rude and frustrating to them.
The NetBeans Platform includes utilities to help you show progress to the user, all of them packed under the Progress API module. This is just a module with two public classes.
There're different use-cases you may want to explore (by reading the javadoc), but the following one is good enough for our needs:
Cancellable myCancellable = ...
ProgressHandle myProgressHandle =
ProgressHandleFactory.createHandle("Cooking noodles, please wait...", myCancellable );
myProgressHandle.start();
myProgressHandle.finish();
This is, you create a ProgressHandle using some text (shown to the user) and a Cancellable object. And then you start() the handle or finish() it.
By default this "ProgressHandle" object is undeterminate (you'll see a progress bar that is continuosly moving). But you can make it determinate and specify the percentage of task you've already finished (see ProgressHandle javadoc for more info).
If you create your ProgressHandle with a Cancellable task (as I've done) then a small button will appear in the UI that allows the user to cancel the task. (See Figure 50, “Progress UI interface”)
A lazy progress UI
The user interface for the progress bar is automatically shown in the lower-left part of the window. As you can see in Figure 50, “Progress UI interface”.
This special component, that visually shows progress to the user, does not appear immediately. This is, if you "start" your progress handle, then the UI does not appear immediately, but a few seconds later. This is good because if your task executes very quickly then nothing is shown to the user (and nothing gets her distracted!). This is a cool behaviour, I'd say. So don't get confused if your UI does not show immediately, just take it easy (and or have some more noodles cooked in your task ;-)).

12.2. The Output Window
Of course we will want to print out the results of our Scheme computations in the NetBeans Output Window. We will also want to read user input from there. [12]
The so called "Output Window" is contained in the I/O APIs, a small package with three classes, two interfaces and a highly scalable mechanism to show very large files in your Swing based application.
To use the "Output Window" you need an "InputOutput" object, used for input (reading stuff from the user) and showing output to the user. And you get an InputOutput object like this:
InputOutput console = IOProvider.getDefault().getIO("Scheme evaluation", true );
(Now, that's what I call a simple API!).
where "Scheme evaluation" is the name of the output tab, and "true" means that we want to open a new tab in case there's none already open (you may want to go take a look at the IOProvider Javadoc for other use cases).
Once you have your "InputOutput" object you can do lots of things:
-
You can select() it, so that it appears on front of other tasks in case it's hidden (you usually do this before starting to output anything to the console, so the user knows that your task is really printing some stuff).
-
You can getOut().println("Hello, world"), for instance, to print out stuff in your output window.
-
And you can do many other things (reading stuff, adding buttons to the console, etc.). To do that you'll need to see the InputOutput javadoc for more details.
12.3. Small summary
So in this section we've learned how to spawn tasks for execution in background, how to show progress to the user and how to print out stuff into the console window.
With these tools we're ready to start implementing our Scheme interpreter.
But that'll require another section. Let's have a rest now. After all our noodle threads are already cooked!
[11] Well, this is not really so, but it's a fairly good explanation, I think.
[12] The Output Window can hold lots of text, and do it quickly and efficiently. The amount of stuff you can hold in the Output Window is limited by the amount of memory in your hard disk, and not in RAM. So don't try to build your own "Output Window". You'll be missing lots of functionality.
13. Invoking Scheme II (Lookup)
In a previous section Section 11, “Invoking Scheme I (creating a Public API)” we defined a Scheme Interpreter Public API as a simple interface.
We also learned how to fire threads for execution, and how to print out stuff to the console window, and how to cancel tasks (see Section 12, “Noodle Threads (threading, progress, console)”).
And we also bundled our preferred Scheme interpreter in a Library Wrapper module (see Section 10, “Wrapping Scheme into our IDE (Library Wrappers)”).
So we have all the tools required to implement that generic Scheme Interpreter interface.
In this section we'll implement that Public API, and we'll learn how to find the implementations of that interface using one of the most important tools in the NetBeans Platform: the Lookup library.
13.1. Invoking Scheme (finally!!!)
Invoking the SISC Scheme Interpreter from Java is not that difficult. There're there's documentation on how to do it, so I won't cover the details here. (I may make a blog entry on that later on).
But let me clarify how I'm doing it with the NetBeans Platform, just in case you're interested in trying out yourself.
The very first step is (of course!) to build a new NetBeans module. I'll be calling it the Scheme SISC Interpreter Module. We will be needing dependencies on the SISC Library Wrapper Module (that contains the SISC libraries) and with the Scheme Interpreter API Module (the one that contains the Scheme Interpreter Interface). [13]
In this new "SISC Interpreter Module" we'll be creating an implementation of the Scheme Interpreter Interface (that was defined a while ago, see Section 11.2.2, “One single interface to rule them all”). The implementation should look something like this:
import (sisc libraries here);
public class SISCSchemeInterpreter implements SchemeInterpreter
{
public String getName() { return "SISC"; }
public void eval( SchemeCallback aCallback, java.io.File aFile )
{
// evaluate a scheme file here using sisc libraries
}
public void eval( SchemeCallback aCallback, java.io.Reader someExpressions )
{
// evaluate a Reader here using sisc libraries
}
}
Of course I've omitted the lengthy details here (but I'll be releasing the source code really soon, in case you're interested. If you're really interested you may want to download a preliminar version).
13.2. Looking-up for a Scheme implementation

So we have a Scheme Interpreter implementation inside our module. To use this exact implementation in another module all we need to do is to add a new dependency with this implementation, then create a "new SISCSchemeInterpreter()" and start using our implementation.
Simple, right?
But, hold down just a minute.
What happens if we have another Scheme interpreter? Shall we add a dependency with that other Scheme intepreter and then invoke it directly? What if we have ten different Scheme interpreters?
What if we want to iterate over all Scheme intepreters available in the system?
The answers to all these questions are included in the NetBeans Lookup Library (the "solution to communication between components"). A great library with lots of functionalities available as a simple jar file [14] that you can reuse in your standalone applications (even in your server-side applications!).
The NetBeans Lookup Library has lots of interesting functionalities. We'll see different applications of the library in upcoming sections. But at the moment we'll concentrate in this great feature: the Lookup Library is compliant with the Service Provider Interface as defined in the Jar File Specification (yes, NetBeans people love following standards), and can be used to register and to search implementations of services in the classpath.
So let's see how we can register our Scheme Interpreter implementation and then how to look-it-up using the Lookup Library.
[13] If you need help on how to define a new module, or on how to add a dependency with an existing module, you may want to go take a look up your answers at the Section 14, “Alphabetical Index”
[14] The "platform6/lib/org-openide-util.jar" file in your NetBeans installation directory
I. Building a standalone NetBeans editor
I.1. Building a standalone NetBeans editor
As I said previously, the NetBeans Platform contains a library called "The NetBeans Editor Library". This is, as far as I know, one of the most powerful open-sourced Swing text libraries out there, fully compliant with the Swing Text API.

Once upon a time, the NetBeans Team did an effort to make this excellent piece of code available as a standalone library. And, as of today, the library can still be used in standalone Swing applications.
In this appendix I present a tiny library that I've cooked that allows me to add a text editor based on the NetBeans Editor Library (this is, a text editor with syntax highlighting, line numbers and lots of cool features) in any Swing application.
Using the NetBeans editor in standalone applications, without the benefits of the whole NetBeans Platform, is somewhat weird. It's like having eggs without bacon (or, as we say here in Spain, "a day without bread"). Since we're going to use just a small set of NetBeans libraries, we'll miss lots of good features from the NetBeans Platform, such as code completion, for instance.
So, before going any further, let me give you a piece of advice: use the standalone NetBeans editor only if you have to (because you have a legacy Swing application, for instance) or as a way to learn about the NetBeans editor internals, or to have a quick and dirty way to test your syntax objects. But I wouldn't recommend you building a Swing application from scratch without using the whole NetBeans Platform. You'll definitely miss it!
The good news is that all the code described in this appendix is highly reusable in your NetBeans Platform based applications!
So let's get our feet wet with the standalone NetBeans editor.
I.1.1. What we need
This is what we need to build a standalone NetBeans editor.
Some NetBeans jar files
First of all we'll need four NetBeans 5.5 jar files (NetBeans 5.0 jar files will do too): org-openide-util.jar, org-netbeans-modules-editor-lib.jar, org-netbeans-modules-editor-util.jar and org-netbeans-modules-editor-fold.jar.
NetBeans 5.5 is released under the CDDL, so I think you can use those files without any legal problems. NetBeans 5.0 is released under the SPL, so there may be some legal concerns if you release those files alone (but I'm not sure: I'm glad I'm not a lawyer ;-)).
Note that those files don't contain all features of the editor. You don't have code completion (org-netbeans-modules-editor-completion.jar) nor bookmarks (org-netbeans-modules-editor-bookmarks.jar), for instance. I've decided to add just as little jars as possible to make the standalone editor runnable, but you're welcome to experiment adding some more jars if you want some extra functionality. You'll end up seeing that the NetBeans Platform is a much better choice, then! ;-)
Some specific classes for your editor
Of course we'll need specific classes for the language we'll be editing: a custom Syntax object (that parses our text), a custom TokenContext object (that specifies the tokens in our language), a custom TokenColoringInitializer (that specifies the colors of our tokens) and a SettingsInitializer (that specifies different editor settings, such as visibility of line numbers, text anti-aliasing, the height of line-separation, and more).
These classes are described somewhere else (Section 8, “Colorful editors: The Old, The Good and The Young”) in this document.
Note that you can reuse all these classes in your applications based on the NetBeans Platform. In fact using this standalone editor is a good way to test your syntax objects!
I have built a small project that contains source code for a Scheme language Syntax object, as well as a SettingsInitializer for Scheme and all those files you need. You may want to use those as a basis to build your custom syntax objects, or reuse some of the excellent NetBeans Syntax objects out there (such as the SQL Syntax).
A tiny library
In order to hide all editor internals I've built a tiny library (CDDL) that eases things. This tiny library is optional: you can either use it or do those internal calls yourself, by hand.
I.1.2. Little by little: Doing things by hand
So let's see what has to be done. Let's start doing things by hand.
.1. Initializing the editor settings
The very first thing we need to do is to initialize the NetBeans Editor Library settings stuff. You can do it yourself, like this:
import org.netbeans.editor.*;
...
Settings.addInitializer( new BaseSettingsInitializer(), Settings.CORE_LEVEL );
Settings.addInitializer( new ExtSettingsInitializer(), Settings.CORE_LEVEL );
Settings.reset();
Or, as we'll see in a minute, you can let the tiny library to do it for you.
.2. Adding your custom settings
After initializing the NetBeans Editor Library settings mechanism, you can add your own settings, using a similar code:
import org.netbeans.editor.*;
...
Settings.addInitializer( new MyCustomSettingsInitializer() );
Settings.reset();
Or, if you wish, you can let the tiny library do it for you too.
Note that the "MyCustomSettingsInitializer" is a class you have to build. This "SettingsInitializer" is valid for a given mime type, so all those settings will be used for all editors of that type.
The "SettingsInitializer" is the place where you specify the settings for your editor, such as if line numbers are to be visible, or if you want antialiased text, or if you want to make the status bar visible, the height between lines in the editor and tons of many other options.
For more information on the set of settings available please see the SettingsNames class.
.3. Registering your editor kit
After adding your settings to the hierarchy of settings, you need to register your editor kit using Swing's registration mechanism (JEditorPane.registerEditorKitForContentType). Again you can do it yourself, like this:
import javax.swing.JEditorPane;
...
MyCustomEditorKit kit = new MyCustomEditorKit();
JEditorPane.registerEditorKitForContentType(
kit.getContentType(),
kit.getClass().getName() );
Or, of course, you can let the tiny library do this for you, as we'll see in a minute.
.4. Adding key bindings
Finally you may want to add your preferred key bindings to a huge variety of actions. You can do it yourself, like this:
JEditorPane pane = new JEditorPane();
pane.setContentType( kit.getContentType() );
pane.getInputMap().put(
KeyStroke.getKeyStroke("DELETE"),
ExtKit.deleteNextCharAction );
Or, again, you can let the tiny library add lots of key bindings for you. Note that the "ExtKit" class has tons of interesting actions that you can reuse in JMenus and JButtons or wherever. This set of actions is the most powerful I've seen so far out there.
.5. To JEditorPane or not: that's the question!
If you have followed all the steps above then you should be able to edit text in your JEditorPane without problems. In fact the JEditorPane will render the different tokens with the colors that you have specified in the TokenColorizer.
So far so good. But, where's the NetBeans editor status bar? Why can't we see a bar with line numbers?
The fact is that those little features are only available if you use a custom JComponent responsible for rendering text. Well, of course! JEditorPanes don't have line numbers after all!
So we need a custom JComponent responsible for rendering the status bar and the line number bar. And such a JComponent is created like this:
JEditorPane myEditorPane = ...
JComponent myEditorComponent =
ExtUtilities.getExtEditorUI( myEditorPane ).getExtComponent();
Or, again, you can use the tiny library as we'll see in a minute.
The created JComponent has some interesting properties. Apart of presenting the line number bar and status bar (if you have made them visible in your custom EditorSettings object), there're some other important things to note:
No JScrollPane needed
The created JComponent already incorporates its own (fast?) scrolling mechanisms, so you don't need to wrap it around a JScrollPane.
JEditorPane XOR JComponent
The JEditorPane and the specific JComponent have a funny behaviour: if you make the JEditorPane visible then the JComponent does not work anymore, and if you make the JComponent visible then the JEditorPane stops working!
I think this is so because the JComponent replaces the JEditorPane UI, and that's why you can either use one or the other.
The important thing to remember is that you want to use a JEditorPane to set text into the editor, but you want to use the JComponent to visualize the JEditorPane content. So remember to make just the JComponent visible (by adding it to a JFrame, for instance) and remember to keep a reference to the JEditorPane to be able to set text into the editor.
I.1.3. A tiny library: Faster, simpler
So having seen the internals of this standalone editor let's see how we can do things easier. The tiny library contains a single class called "NBEditorFactory". Let's see how to use it by using the following example:
/** Creates new form NBEditorLibDemoFrame */
public NBEditorLibDemoFrame()
{
initComponents();
// Create an editor kit for Scheme
SchemeEditorKit editorKit = new SchemeEditorKit(); ①
// Initialize Scheme language support
NBEditorFactory.addSyntax( editorKit, new SchemeSettingsInitializer() ); ②
// Create a plain editor pane
JEditorPane editorPane = new JEditorPane();
// Create a renderer to replace the editor pane *visually*
JComponent renderer =
NBEditorFactory.newTextRenderer( editorKit, editorPane ); ③
// Set the text *in the editor pane*
editorPane.setText("; A scheme definition\n(define i (sqrt -1 ))\n"); ④
// Visualize the *renderer*
getContentPane().add( renderer, BorderLayout.CENTER ); ⑤
Let's see what the code above does:
① Creates a new ExtEditorKit for the Scheme language (the source code for SchemeEditorKit is available in the example).
② Initializes the editor settings (if needed), and then registers the SchemeSyntax object and the Scheme editor settings. (Source code for SchemeSyntax and SchemeSettingsInitializer available in the example).
③ Creates the custom JComponent to be used instead of the JEditorPane for visualization purposes.
④ Adds some text into the JEditorPane. Note that we keep on using the JEditorPane to add text to the editor, but we will use the JComponent for visualization purposes...
⑤ Adds the JComponent to the frame, to visualize text. Note that we don't add the JEditorPane, but the JComponent instead.
I.1.4. Do it yourself!
So what are you waiting for? Do it yourself! Now you know how to do it! Don't you? Let me review the basics again for you, just in case:
Build the syntax, settings and other files for your language
Start by taking a look at the the NetBeans Syntax Highlighting Tutorial (hurry up, this is going to change with the new syntax support!). You may also go take a look at the Section 8, “Colorful editors: The Old, The Good and The Young” and to the Section 9, “Adding Syntax Support” sections.
Get the tiny library
Or build your own. You can download it from my attic. Don't forget to get the jar files from a working NetBeans 5.5 IDE.
And don't forget...
... that using the NetBeans Editor Library as a standalone editor is probably a bad idea. The NetBeans Platform has lots of good stuff in there you can't miss! Keep tuned for more news, and have fun editing!
14. Alphabetical Index
Alphabetical Index
A
Autoload module, One for all, and all for one!
B
BaseKit, NetBeans' delicious EditorKits
BaseOptions, Options and BaseOptions
C
ClassLoader
Link to further information, Don't shout: I can't hear you anyway
ClassLoaders
One per module, Don't shout: I can't hear you anyway
ClassNotFoundException
requirements to meet to avoid ClassNotFoundExceptions, Don't shout: I can't hear you anyway
close(), in ModuleInstall, Executing Java code on module initialization
closing(), in ModuleInstall, Executing Java code on module initialization
Console (see Output Window)
D
dependencies, Using... and being used: dependencies
cyclic, I need you, you need me, I need you...
declared in the Project Metadata file, Adding dependencies to other modules
how to declare one with a module, Adding dependencies to other modules
transitive, I need you, you need him, I don't know him
E
Eager module, One for all, and all for one!
editor
EditorKits, NetBeans' delicious EditorKits
registering EditorKits, ... and registering our SchemeEditorKit
standalone editor, Building a standalone NetBeans editor
ExtKit, NetBeans' delicious EditorKits
I
I/O APIs (see Output Window)
Important Files
Project Metadata, Adding dependencies to other modules
initialization
of modules, One for all, and all for one!
of modules, using ModuleInstall, Executing Java code on module initialization
L
library wrapper, Modules, Module Suites and Library Wrappers
library wrappers
definition, Library Wrappers
lookup
global lookup, La bolsa global
introduction, So, where's my object?
looking-up objectxs, Looking-up objects
Lookups.fixed, Otros tipos de bolsas
performance, Complex queries, performance and... thieves!
Lookup
used to find interface implementations, Looking-up for a Scheme implementation
M
meta-inf/services
cómo buscarlos con Lookup, La bolsa global
module suites, Modules, Module Suites and Library Wrappers
modules, Modules, Module Suites and Library Wrappers
public API, Public APIs, exported packages, documentation and the importance of APIs
versions, Embracing change
N
NbEditorKit, NetBeans' delicious EditorKits
NetBeans Modules
Public APIs
API Design and API Review Tutorials, Public APIs, exported packages, documentation and the importance of APIs
degrees of stability, Public APIs, exported packages, documentation and the importance of APIs
javadoc, Public APIs, exported packages, documentation and the importance of APIs
O
options
system options
for editors, Options and BaseOptions
Output Window, The Output Window
P
Progress UI API, Showing progress
Project Metadata
and dependencies, Adding dependencies to other modules
Public API
changes in, What about environments?
creating one, Making our interface public
R
Regular module, One for all, and all for one!
restored(), in ModuleInstall, Executing Java code on module initialization
S
Service Provider Interface (see Lookup)
SettingsInitializer, The old way: overview
suites (see module suites)
Syntax
overview, The old way: overview
syntax highlighting
creating a custom Syntax object, Syntax - non functional requirements
for multiple languages (JSPs, etc.), Multi syntaxes
overview of basic syntax highlighting, The old way: overview
plain syntax, Using a plain syntax
SettingsInitializer, The old way: overview
Syntax - overview, The old way: overview
syntax highlighting mechanisms, Adding color to editors: The Old, The Good and The Young!
TokenColoringInitializer, The old way: overview
TokenContext, The old way: overview
T
threading
and the RequestProcessor, Threading with the RequestProcessor
Showing progress to the user, Showing progress
TokenColoringInitializer, The old way: overview
TokenContext, The old way: overview
U
uninstalled(), in ModuleInstall, Executing Java code on module initialization
V
validate(), in ModuleInstall, Executing Java code on module initialization
versions, Embracing change
and Public APIs, Making our interface public
X
XML FileSystem, The internals of the XML layer file
XML Layer, Sandwiches!! (XML Layer Files)
adding Java object instances, ... and registering our SchemeEditorKit
attributes, Attributes
examples of use, What are sandwiches good for?
files, Files
folders, Folders
how they work, How sandwich files work
how to see the whole sandwich, Watching the sandwich