# Plugging In SubSystems

The `org.eclipse.rse.core.subsystemConfigurations` extension point is defined in the plugin `org.eclipse.rse.ui`. This is the most complex extension point to use, but also the most powerful. It enables tool providers to register a class that creates subsystem objects, which appear under a connection when a connection is expanded in the Remote Systems view. For example, here is an iSeries connection with four subsystems, each created by a subsystem configuration registered with this extension point.

The extension markup is quite simple for this extension point, as it has only one element, `<configuration>`, with only a few simple attributes to supply:

- id. Unique id for the extension, as required for all extensions. There is also a way to query a subsystem configuration object via its ID.
- vendor. Your company name, shown in properties dialog for subsystems created by this subsystem configuration.
- icon. The icon displayed in the Remote Systems view for each subsystem created by this subsystem configuration.
- iconlive. The icon used when the subsystem is physically connected to its remote system.
- name. The name displayed in the Remote Systems view for each subsystem created by this subsystem configuration.
- systemTypeIds. A semi-colon separated list of system type IDs which this subsystem configuration supports. When a user creates a connection, this configuration will only be asked to create a subsystem for connections to systems of these types. Wildcards are supported; in order to register against all system types, specify a single "*".
- serviceType. An optional semi-colon separated list of names and transports that can be used to match this service with remotelly advertised services through DNS-SD or any other supported service discovery protocol. The name would usually be the keyword used by the IANA or by DNS SRV service types (RFC 2782).
- category. A name used to categorize this subsystem's functionality. Used by the popupMenus and propertyPages extension points to allow actions and property pages to be scoped to resources shown in subsystems of a particular category. Multiple subsystems can have the same category.
- class. A class implementing ISubSystemConfiguration interface, as described in the following programming details section.

## Programming Details

It is important to remember what the purpose of a subsystem is, and how it fits in the overall RSE model, so as to understand the programming details for supporting subsystems via this subsystem configuration extension point. Minimally speaking, this extension point requires a class that implements the interface `ISubSystemConfiguration`. Ultimately, the intent of a subsystem configuration is to provide individual subsystem instances to each connection, and the intent of a subsystem instance is to present remote resources for display or manipulation purposes. Thus, you must also create a class implementing the interface `ISubSystem`.
The intent of each subsystem is to show remote resources from the remote system identified by the parent connection, for the user. (Subsystems can in fact be hidden, which means their their role is to return remote resources for programmatic purposes only.) When the first request is made for remote objects, the subsystem is asked to connect to the remote system if it is not already. This job is deferred to a IConnectorService object whose role it is to manage connecting and disconnecting to the remote physical system. By use of a connector service manager, one system can manage the live connections of multiple subsystems in the same system connection, should they happen to share the same communication pipe. If filters are supported (the default), the first connection is made, and the remote resources are subsequently shown, when filters within the subsystem are expanded, which results in a call to `resolveFilterString` in the subsystem object.
Furthermore, you will want to supply your own new-filter and change-filter actions. If filters are not supported, then these remote resources are shown immediately when the subsystem itself is expanded, via a call to `getChildren`. Either way the resulting resources are displayed to the user. To facilitate the displaying of these objects in the RSE views, the objects themselves must implement the Eclipse IAdaptable interface (to enable the property sheet viewer) and there must be a specific RSE view adapter and an RSE remote-information adapter registered for the remote objects, which the RSE views consult to get the labels, images, actions, and property sheet values for the remote objects. Typically, you will supply actions by leveraging the user interface elements supplied by the RSE, such as base classes for messages, actions, dialogs, wizards, property pages and preference page editors. You will probably also supply a property page for your subsystem objects, via the Eclipse `propertyPages` extension point, and for your remote resource objects, via the RSE propertyPages extension point.

### Base Classes

For many of the interfaces you must implement, there are base classes supplied that you can extend to make the development effort easier.

The following summarizes the minimum set of classes you will be creating in order to realize your own subsystem support, including the RSE-supplied base classes to extend:

Class(es) | Base Class | Description
--- | --- | ---
subsystem configuration | `SubSystemConfiguration` | The factory class responsible for creating instances of subsystem class
subsystem | `SubSystem` | The subsystem class. There will be one instance created for each connection. In addition to storing your unique attributes, this must return the remote resource objects when a filter is expanded within the subsystem. How that communication with the remote system is done is left up to you.
system | `AbstractConnectorService` | Represents and manages a live connection to the remote system, doing the connecting and disconnecting.
connector service manager | `AbstractConnectorServiceManager` | Manages a single connector service instance that is shared among multiple subsystems in a single connection. Even if you only have a single subsystem configuration it is useful to use this in case you later add additional factories, and their subsystems share the same communication pipe. To enable this, all your subsystem classes need to implement a unique interface of your own creation.
remote resource | `AbstractResource` | Can be used as a base class for the objects representing remote resources.
new-filter wizard | `SystemNewFilterAction` and `SystemFilterStringEditPane` | Displays a wizard prompting for a new filter. Filters contain filter strings, which are up to each subsystem to design and interpret. The New Filter wizard prompts for a single filter string (more can be added in change mode). Typically you subclass `SystemFilterStringEditPane` to create your own prompt for the filter string information, and then subclass `SystemNewFilterAction` so as to configure the default New Filter wizard to use your edit pane in the first page.
change-filter dialog | `SystemChangeFilterAction` and `SystemFilterStringEditPane` | Displays a dialog prompting to change an existing filter. The default dialog allows the user to create and edit filter strings. Typically, you override the `SystemChangeFilterAction` class, and configure the dialog to use the same edit pane used in the New Filter wizard.
remote element adapter | `AbstractSystemViewAdapter` and `ISystemRemoteElementAdapter` | The view adapter is an amalgamation of all the required information needed to populate the RSE views. You will define one class per unique remote object interface or class, and in it you will override methods to return the remote object's label, image, popup-menu actions, property sheet properties and children (if expandable). You can also decide whether to enable common RSE popup menu actions like rename, delete and refresh. Your view adapter will usually also implement the remote adapter interface, enabling the many common RSE capabilities to work, such as the copy, paste, drag and drop, and more.

### Overview of Steps

Implementing a subsystem involves the following steps, in the following order:

1. Creating an interface for your subsystem. It can, and often is, an empty interface.
2. Creating a subclass of AbstractConnectorService. The code here will interact as necessary with your subsystem to manage the connection lifecycle to the remote system.
3. Creating a subclass of AbstractConnectorServiceManager. The code here will re-use the same IConnectorService object from step 2 for all subsystems that implement the interface from step 1, within the same connection.
4. Designing the classes to represent the remote resources (your model) that you will show from your subsystem. Each must implement the `org.eclipse.core.runtime.IAdaptable` interface from Eclipse. It is also very helpful if they also maintain a reference to the subsystem which created them. The base class AbstractResource is offered to help with this.
5. Designing the syntax of the filter string that will be used as a pattern to tell your subsystem what resources to show. For example, for files this might be of the form "path/generic-name /options". It is the job of your subsystem to interpret these strings and return a list of remote resources matching the criteria capturing in the string. You will eventually design a user interface to prompt the user for one the contents of one of these filter strings. You might find it helps to create a class that holds one of these filter strings passed via a constructor, and can parse it into its constituent pieces via getter methods. It should also support a default constructor and setting of constituent pieces via setter methods, and the generation of the filter string via toString().
6. Creating a subclass of SubSystem that implements the interface you designed in step 1. This will:
   - manage persistent properties via calls to the inherited createPropertySet, getPropertySet and related methods,
   - use your communications layer to return instances of your model objects in its internalResolveFilterString method. The input to this is one or more strings such as you designed in step 5. It will return all remote resources matching the criteria captured in the input filter string. You may also find the org.eclipse.rse.services.clientserver.NamePatternMatcher class to be handy in comparing a generic pattern to a particular input. This class is in the `runtime/clientserver.jar` file, and has no eclipse-dependencies, so it can be used in your client subsystem code, or your server-side code.
7. Creating a subclass of SubSystemConfiguration.
8. Defining your subsystemConfigurations extension in your `plugin.xml` file.
9. For each remote resource class you created in step 4, you need to create an adapter class, which extends AbstractSystemViewAdapter and which implements ISystemRemoteElementAdapter.
10. Register your adapters with the platform. First you create an adapter class that extends `AbstractSystemRemoteAdapterFactory` and implements interface `org.eclipse.core.runtime.IAdapterFactory`. Next, in the `startup()` method of your plugin class, add code to instantiate the class and register the object with the platform adapter manager, once for each class in your resource model. For example:
    `MyAdapterFactory factory = new MyAdapterFactory(); // extends AbstractSystemRemoteAdapterFactory
    IAdapterManager manager = Platform.getAdapterManager();
    manager.registerAdapters(factory, MyModelObject1.class);
    manager.registerAdapters(factory, MyModelObject2.class);
    `
11. If your filter string from step 5 is complicated enough, you will probably find the RSE-supplied filter wizard and change-dialog insufficient. The idea with these is that the New Filter wizard prompts in its first page for a single filter string. The change dialog allows the user to change that single filter string, or add additional filter strings. To change these for your subsystem, you need to:
    1. Create your own filter string edit pane subclass that contains your own GUI prompts as desired.
    2. Create your own new-filter wizard action subclass, and configure it to use your own edit pane subclass by overriding `configureNewFilterWizard` and in it calling `setFilterStringEditPane` on the given wizard.
    3. Create your own change-filter action subclass, and configure it to use your own edit pane subclass by overriding `configureFilterDialog` and in it calling `setFilterStringEditPane` on the given dialog.
    4. Override the `getNewFilterPoolFilterAction(SystemFilterPool, Shell)` method in your subsystem configuration, to configure your new-filter action. You can actually avoid creating an action subclass if you choose, by calling the configuration methods in the RSE-supplied new-filter action class.

See the subsystem tutorial for a step-by-step example.