1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<META HTTP-EQUIV="Content-Style-Type" CONTENT="text/css">
<meta name="copyright" content="Copyright (c) IBM Corporation and others 2002, 2008. This page is made available under license. For full details see the LEGAL in the documentation book that contains this page." >
<!-- David Dykstal (IBM) - [193747] updated links and corrected syntax errors -->
<LINK REL="STYLESHEET" HREF="../../book.css" TYPE="text/css">
<title>Plugging In SubSystems</title>
</head>
<body bgcolor="#ffffff">
<h1>Plugging In SubSystems</h1>
<p>The <samp><A href="../../reference/extension-points/org_eclipse_rse_core_subsystemConfigurations.html">org.eclipse.rse.core.subsystemConfigurations</a></samp>
extension point is defined in the plugin <samp>org.eclipse.rse.ui</samp>.
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, <A href="RSView_iSeries.gif">here is an iSeries connection</A> with four subsystems,
each created by a subsystem configuration registered with this extension point.
</p>
<p>The <A href="../../reference/extension-points/org_eclipse_rse_core_subsystemConfigurations.html">extension markup</A> is quite simple for this extension point,
as it has only one element, <b><samp><configuration></samp></b>, with only a few simple attributes to supply:
</p>
<ul>
<li><b>id</b>.
Unique id for the extension, as required for all extensions.
There is also a way to <A href="../../reference/api/org/eclipse/rse/core/model/ISystemRegistry.html#getSubSystemConfiguration(java.lang.String)">query</A> a subsystem configuration
object via its ID.</li>
<li><b>vendor</b>.
Your company name, shown in properties dialog for subsystems created by this subsystem configuration.</li>
<li><b>icon</b>.
The icon displayed in the Remote Systems view for each subsystem created by this subsystem configuration.</li>
<li><b>iconlive</b>.
The icon used when the subsystem is physically connected to its remote system.</li>
<li><b>name</b>.
The name displayed in the Remote Systems view for each subsystem created by this subsystem configuration.</li>
<li><b>systemTypeIds</b>.
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 "*".</li>
<li><b>serviceType</b>. 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 <A href="http://www.iana.org/assignments/port-numbers">IANA</A>
or by <A href="http://www.dns-sd.org/ServiceTypes.html">DNS SRV service types (RFC 2782)</A>.</li>
<li><b>category</b>. A name used to categorize this subsystem's functionality. Used by the <A href="popup.html">popupMenus</A>
and <A href="propertypage.html">propertyPages</A> 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.</li>
<li><b>class</b>. A class implementing <A href="../../reference/api/org/eclipse/rse/core/subsystems/ISubSystemConfiguration.html">ISubSystemConfiguration</A>
interface, as described in the following programming details section.</li>
</ul>
<h2>Programming Details</h2>
<p>It is important to remember what the purpose of a subsystem is, and how it fits in the overall RSE <A
href="../Model.html">model</A>, 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
<samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/ISubSystemConfiguration.html"><B>ISubSystemConfiguration</B></A></samp>.
Ultimately, the intent of a subsystem <I>configuration</I> is to provide individual
subsystem <I>instances</I> 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 <samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/ISubSystem.html"><B>ISubSystem</B></A></samp>.
<BR>
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 <A href="../../reference/api/org/eclipse/rse/core/subsystems/IConnectorService.html">IConnectorService</A> object whose role it is to manage connecting and disconnecting
to the remote physical system. By use of a <A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractConnectorServiceManager.html">connector service manager</a>,
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 <A href="../../reference/api/org/eclipse/rse/core/subsystems/ISubSystemConfiguration.html#supportsFilters()">supported</A>
(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
<samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystem.html#internalResolveFilterString(java.lang.String,%20org.eclipse.core.runtime.IProgressMonitor)">resolveFilterString</A></samp>
in the subsystem object. <BR>
Furthermore, you will want to supply your own
<B><A
href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemNewFilterAction.html">new-filter</A></B> and
<A href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemChangeFilterAction.html"><B>change-filter</B></A> actions.
If filters are not supported, then these remote resources are shown immediately when the subsystem itself is expanded, via a call to
<samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/ISubSystem.html#getChildren()">getChildren</A></samp>.
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
<B><A
href="../../reference/api/org/eclipse/rse/ui/view/AbstractSystemViewAdapter.html">view
adapter</A></B>
and an RSE <B><A
href="../../reference/api/org/eclipse/rse/ui/view/ISystemRemoteElementAdapter.html">remote-information
adapter</A></B>
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
<A href="../api/uiAPI.html">user interface elements</A> supplied by the RSE, such as base classes for
<A href="../api/messages/uiMessageAPI.html">messages</A>,
<A href="../api/actions/uiActionsAPI.html">actions</A>,
<A href="../api/dialogs/uiDialogsAPI.html">dialogs</A>,
<A href="../api/wizards/uiWizardsAPI.html">wizards</A>,
<A href="../api/properties/uiPropertiesAPI.html">property pages</A> and
<A href="../api/preferences/uiPreferencesAPI.html">preference page editors</A>. You will probably also supply a
property page for your subsystem objects, via the Eclipse <samp>propertyPages</samp> extension point, and for your remote resource objects, via the RSE <A
href="propertypage.html">propertyPages</A> extension point.</p>
<h3>Base Classes</h3>
<P>For many of the interfaces you must implement, there are base classes supplied that you can extend to make the development effort easier.</P>
<p>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:</p>
<TABLE border="1">
<TBODY>
<TR>
<TH>Class(es)</TH>
<TH>Base Class</TH>
<TH>Description</TH>
</TR>
<TR>
<TD>subsystem configuration</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystemConfiguration.html">SubSystemConfiguration</A></samp></TD>
<TD>The factory class responsible for creating instances of subsystem class</TD>
</TR>
<TR>
<TD>subsystem</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystem.html">SubSystem</A></samp></TD>
<TD>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.</TD>
</TR>
<TR>
<TD>system</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractConnectorService.html">AbstractConnectorService</A></samp></TD>
<TD>Represents and manages a live connection to the remote system, doing the connecting and disconnecting.</TD>
</TR>
<TR>
<TD>connector service manager</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractConnectorServiceManager.html">AbstractConnectorServiceManager</A></samp></TD>
<TD>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.</TD>
</TR>
<TR>
<TD>remote resource</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractResource.html">AbstractResource</A></samp></TD>
<TD>Can be used as a base class for the objects representing remote resources.</TD>
</TR>
<TR>
<TD>new-filter wizard</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemNewFilterAction.html">SystemNewFilterAction</A></samp> and
<samp><A href="../../reference/api/org/eclipse/rse/ui/filters/SystemFilterStringEditPane.html">SystemFilterStringEditPane</A></samp></TD>
<TD>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 <samp>SystemFilterStringEditPane</samp> to create your own
prompt for the filter string information, and then subclass <samp>SystemNewFilterAction</samp> so as to configure the default New Filter wizard to use
your edit pane in the first page.</TD>
</TR>
<TR>
<TD>change-filter dialog</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemChangeFilterAction.html">SystemChangeFilterAction</A></samp> and
<samp><A href="../../reference/api/org/eclipse/rse/ui/filters/SystemFilterStringEditPane.html">SystemFilterStringEditPane</A></samp></TD>
<TD>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 <samp>SystemChangeFilterAction</samp> class, and configure the dialog to use the same edit pane used in the New Filter wizard.
</TD>
</TR>
<TR>
<TD>remote element adapter</TD>
<TD><samp><A href="../../reference/api/org/eclipse/rse/ui/view/AbstractSystemViewAdapter.html">AbstractSystemViewAdapter</A></samp> and
<samp><A href="../../reference/api/org/eclipse/rse/ui/view/ISystemRemoteElementAdapter.html">ISystemRemoteElementAdapter</A></samp>
</TD>
<TD>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. <BR>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. </TD>
</TR>
</TBODY>
</TABLE>
<h3><A name="steps"></A>Overview of Steps</h3>
<p>Implementing a subsystem involves the following steps, in the following order:</p>
<OL>
<li>Creating an interface for your subsystem. It can, and often is, an empty interface.</li>
<li>Creating a subclass of <A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractConnectorService.html">AbstractConnectorService</A>.
The code here will interact as necessary with your subsystem to manage the connection lifecycle to the remote system.</li>
<li>Creating a subclass of <A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractConnectorServiceManager.html">AbstractConnectorServiceManager</A>.
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.</li>
<li>Designing the classes to represent the remote resources (your <i>model</i>) that you will show from your subsystem.
Each must implement the <samp>org.eclipse.core.runtime.IAdaptable</samp> interface from Eclipse.
It is also very helpful if they also maintain a reference to the subsystem which created them. The base class
<A href="../../reference/api/org/eclipse/rse/core/subsystems/AbstractResource.html">AbstractResource</A> is offered to help with this.</li>
<li>Designing the syntax of the <i>filter string</i> 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().
</li>
<li>Creating a subclass of <A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystem.html">SubSystem</A>
that implements the interface you designed in step 1. This will:
<ul>
<li>manage persistent properties via calls to the inherited <A href="../../reference/api/org/eclipse/rse/core/model/PropertySetContainer.html#createPropertySet(java.lang.String)">createPropertySet</A>,
<A href="../../reference/api/org/eclipse/rse/core/model/PropertySetContainer.html#getPropertySet(java.lang.String)">getPropertySet</A> and related methods,</li>
<li>use your communications layer to return instances of your model objects in its <A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystem.html#internalResolveFilterString(java.lang.String,%20org.eclipse.core.runtime.IProgressMonitor)">internalResolveFilterString</A> 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 <A href="../../reference/api/org/eclipse/rse/services/clientserver/NamePatternMatcher.html">org.eclipse.rse.services.clientserver.NamePatternMatcher</a>
class to be handy in comparing a generic pattern to a particular input. This class is in the <samp>runtime/clientserver.jar</samp> file,
and has no eclipse-dependencies, so it can be used in your client subsystem code, or your server-side code.</li>
</ul>
</li>
<li>Creating a subclass of <A href="../../reference/api/org/eclipse/rse/core/subsystems/SubSystemConfiguration.html">SubSystemConfiguration.</A></li>
<li>Defining your <A href="../../reference/extension-points/org_eclipse_rse_core_subsystemConfigurations.html">subsystemConfigurations extension</a> in your <samp>plugin.xml</samp> file.</li>
<li>For each remote resource class you created in step 4, you need to create an adapter class, which extends
<A href="../../reference/api/org/eclipse/rse/ui/view/AbstractSystemViewAdapter.html">AbstractSystemViewAdapter</A> and which
implements <A href="../../reference/api/org/eclipse/rse/ui/view/ISystemRemoteElementAdapter.html">ISystemRemoteElementAdapter</A>.
</li>
<li>Register your adapters with the platform. First you create an
adapter class that extends <samp><a href="../../reference/api/org/eclipse/rse/ui/view/AbstractSystemRemoteAdapterFactory.html">AbstractSystemRemoteAdapterFactory</a></samp>
and implements interface <samp><b>org.eclipse.core.runtime.IAdapterFactory</b></samp>. Next,
in the <samp>startup()</samp> 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:
<br><samp>
MyAdapterFactory factory = new MyAdapterFactory(); // extends AbstractSystemRemoteAdapterFactory<br>
IAdapterManager manager = Platform.getAdapterManager();<br>
manager.registerAdapters(factory, MyModelObject1.class);<br>
manager.registerAdapters(factory, MyModelObject2.class);<br>
</samp>
</li>
<li>If your filter string from step 5 is complicated enough, you will probably find the
RSE-supplied <a href="NewFilterWizard_Default.gif">filter wizard</a> and
<a href="ChangeFilterDialog_Default.gif">change-dialog</a> 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:
<ol>
<li type="i">Create your own
<a href="../../reference/api/org/eclipse/rse/ui/filters/SystemFilterStringEditPane.html">filter string edit pane</a>
subclass that contains your own GUI prompts as desired.</li>
<li type="i">Create your own
<a href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemNewFilterAction.html">new-filter wizard action</a>
subclass, and configure it to use your own edit pane subclass by overriding
<samp><a href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemNewFilterAction.html#configureNewFilterWizard(org.eclipse.rse.ui.filters.dialogs.SystemNewFilterWizard)">configureNewFilterWizard</a></samp>
and in it calling <samp><a href="../../reference/api/org/eclipse/rse/ui/filters/dialogs/SystemNewFilterWizard.html#setFilterStringEditPane(org.eclipse.rse.ui.filters.SystemFilterStringEditPane)">setFilterStringEditPane</a></samp>
on the given wizard.</li>
<li type="i">Create your own
<a href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemChangeFilterAction.html">change-filter action</a>
subclass, and configure it to use your own edit pane subclass by overriding
<samp><a href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemChangeFilterAction.html#configureFilterDialog(org.eclipse.rse.ui.filters.dialogs.SystemChangeFilterDialog)">configureFilterDialog</a></samp>
and in it calling <samp><a href="../../reference/api/org/eclipse/rse/ui/filters/dialogs/SystemChangeFilterDialog.html#setFilterStringEditPane(org.eclipse.rse.ui.filters.SystemFilterStringEditPane)">setFilterStringEditPane</a></samp>
on the given dialog.</li>
<li type="i">Override the <samp><a href="../../reference/api/org/eclipse/rse/ui/subsystems/ISubSystemConfigurationAdapter.html#configureNewFilterAction(org.eclipse.rse.core.subsystems.ISubSystemConfiguration,%20org.eclipse.rse.ui.filters.actions.SystemNewFilterAction,%20java.lang.Object)">getNewFilterPoolFilterAction(SystemFilterPool, Shell)</a></samp>
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 <a href="../../reference/api/org/eclipse/rse/ui/filters/actions/SystemNewFilterAction.html">new-filter action class</a>.</li>
</ol>
</li>
</OL>
<br><hr>
<p>See the <a href="../tutorial/subsystem.html">subsystem tutorial</a> for a step-by-step example.</p>
</body>
</html>
|