Overview

The module is called zeroadmin because it should allow for "Zero Administration" client being made from a NetBeans distribution. The module should enable writing the user configuration to a remote storage using J2EE Session bean(s).

Use cases

The use cases are divided into two categories: User Experience and Administrator.

User experience

The user should be able to use the application as if loaded locally. The way the application starts is covered by different module.

Reset configuration

As the user customizes the applicatoin it might happen that (s)he needs to reset the configuration to the initial state. There is an action (in menu) to to the reset. After this action is selected the overall state of the application is transferred to the initial state.

Refresh from default configuration

If the default configuration is changed while the user has already done some customizations there has to be way to get those changes to the user's configuration. This can be either automatic or an action present in the menu could do the manual Refresh.

Administrator

The administrator is responsible for installing the application.

User data

The user data are stored on the J2EE application server for each user. The user data can be manipulated easily - e.g. delete, copy, backup etc.

Operator data

There are special configuration data (referred to as "Operator's config") that serve as the default configuration for the new users. This config can be saved from an ordinary application session. The operator's config is saved in the same format as the user data.

Requirements

The module (together with patches in the core) should

Functionality

The module's code is described in this chapter.

Prerequisities

In order for the module to work properly with NetBeans 3.5 the core has to be patched (as in branch platform_32247) in following classes:

Connection to the J2EE server

When the module is initialized it uses the j2ee APIs (JNDI in this case) to get a remote reference to a session bean that stores the content of the system file system.

Currently the API for the bean is following:

public interface ConfigStorage extends javax.ejb.EJBObject {
    public void saveUserData(char[] data) throws java.rmi.RemoteException;
    public void saveOperatorData(char[] data) throws java.rmi.RemoteException;
    public char[] getUserData() throws java.rmi.RemoteException;
    public char[] getOperatorData() throws java.rmi.RemoteException;
}
The terminology might be a bit confusing here and it might be changed if it is too confusing. "Operator" means defaults for all users. The "User" is data stored individually for each user. "Data" is the content of the system file system converted to text (the conversion is described bellow). "Log" is the content of the ide.log file.

SystemFileSystem made to run with MemoryFileSystem

MemoryFileSystem is used as the writable layer for the system file system instead of ExLocalFileSystem. The MemoryFilesystem code was already in core ready to be used. The functionality added by the zeroadmin module populates the contents of the MemoryFileSystem from a remote connection.

When the module is started the both the operator and user data are fetched from the database and copied to the memory file system. The operator data are copied first and then they are overwritten by the user config (originally I thought of using two layers but system file system bahaved strangely in this setup).

Logging

The module provides an implementation of ErrorManager that sends all output to loggers from java.util.logging.* API.

The Logger from java.util.logging API has to be instanciated in the ErrorManager. The name of the Logger has to be the name of the ErrorManager instance. The Loglevel has to be adapted to the correct level.

    In the Java Logging API there are 7 levels of severity:
  1. SEVERE (highest value)
  2. WARNING
  3. INFO
  4. CONFIG
  5. FINE
  6. FINER
  7. FINEST (lowest value)
    In Netbeans there are 6 levels of severity:
  1. ERROR (highest value)
  2. EXCEPTION
  3. INFORMATIONAL
  4. UNKNOWN
  5. USER
  6. WARNING (lowest value)
Only the most severe levels (SEVERE and WARNING) are written by default in Java Logging API. In the FileHandler only SEVERE and WARNING messages are logged. In contrast to Java Logging API the Warning is less severe in Netbeans. The following mapping of Severity levels is used:
Java Logging API Netbeans API
SEVERE (highest value) ERROR
WARNING EXCEPTION
INFO INFORMATIONAL, USER, UNKNOWN
CONFIG
FINE WARNING
FINER
FINEST (lowest value)

The class LoggingErrorManager does not replace NbErrorManager from core but it adds additional functionality - logging using java.util.logging.*. We do not provide user notification, it is left for the core implementation.

Configuration and customization

The code implementing the session bean (ConfigStorageBean.java) is a demonstration code only running with cloudscape database (which is included in J2EE SDK RI from Sun). The code accessing the database is not optimal and should be treated as a demo only.

The access to the database is preconfigured to use the default cloudscape db. In order to run on a different db the code in methods saveData , getData should be changed. Also the deployment solution called from the build script should be changed (build.xml for the zeroadmin module, target ejbs.

The build script assumes deployment on "localhost" - the whole deployment solution is for testing only. You might face problems with the build script when trying to access the server from a remote machine.

Implementation

There were several possiblities for implementation given the initial requirements. I have chosen a mixed approach modifying some of the core classes and putting some code to the zeroadmin module. The changes in core are trying to be general enough in hope that they can be included in future versions of NetBeans. The module should contain code that is not suitable for core - especially the EJB usage is something that is IMHO better kept outside core.

XMLBufferFileSystem

For creating the textual representation of the system file system the code originally from API Support module was taken and adapted. It produces data conforming to the XML file system DTD (which can be found here).

The only notable difference in the XML format is inclusion of the binary data directly in body of the XML document. The file still conforms to the DTD but one attribute is handled specially: "XMLBufferFileSystem.binary". When there is a file with this atribute set to true the contents of the file is binary data converted to text by the same routine used by the serial data convertor (from core/projects). If the file is not binary the content of the file is directly included as CDATA element.

Dependence on core

The code in the zeroadmin module uses dependency on core and reflection to access the MemoryFilesystem. The reflection is used in the ZeroAdminProjectManager method to access fields from classes in core.

Installation

The module needs to run the initialization code on every startup. The code is not in regular ModuleInstall but the module registers an instance or org.netbeans.core.projects.TrivialProjectManager in META-INF/services lookup. TrivialProjectManager is not public API of core but is as currently seen the only way to invoke our code reasonably late during exit.

Testing

Since there are two implementations of a filesystem that this module exposes (MemoryFilesystem was already there but was not used nor tested before) I have copied the set of tests from core that should test all different aspects of a file system implementation. I have copied this code to zeroadmin module to be able to run them on XMLBufferFilesystem easily). Possible place for improvement is to call the tests from core and delete their copies from the zeroadmin module.

In order to test the storage to server a small module containing one setting is also included under the unit tests folder. This module can be used to check content of the database by simply calling one action that creates some number of files on the system file system.

The tests checking the interoperability of the module with the core and with the J2EE server are in class RemoteStorageTest. In order to run these tests the module has to be able to connect to the J2EE server.