Jump to: navigation, search

Difference between revisions of "Equinox Extension Registry Work"

 
Line 1: Line 1:
 
'''WORK IN PROGRESS – SUBJECT TO CHANGE'''
 
'''WORK IN PROGRESS – SUBJECT TO CHANGE'''
 +
= Improving usability of the extension registry =
  
== Problem ==
+
This page tracks current state, plans, and intentions for the extension registry enhancements.
  
When developers use extension registry, the most common first step is to translate registry artifacts (IExtension, IConfigurationElement) into user-specific classes. Even in a most trivial case that results in a few lines of extra code. The "proper" implementation that takes into account multiplicity, dynamic registry events, and error handling takes a bit of knowledge and effort.
+
Please feel free to add comments to it.
  
As a result we have to deal with:
+
== Areas ==
* Extra code that has to be written by each developer for parsing and walking extension registry;
+
* Inconsistent treatment of extension information not conforming to the schema;
+
* Problems in synchronizing user model and registry.
+
  
 +
* [[Equinox Extension Registry Work Objects| Create user-specific objects based on the contents of the configuration
 +
elements]]
 +
* Expand ability to programmatically modify extension registry
 +
* Add support for non-singleton bundles
 +
* Add support for switching NLS locale without restart
  
== Proposed solution ==
+
== Restrictions ==
 +
* At least for 3.x streams we need to continue supporting pre-1.5 VMs. As such, any functionality based on annotations can only be used in an optional role
  
Let's assume that extension point schemas can specify Java classes corresponding to schema elements. When such information can be used to construct Java classes and inject them with the values specified in the plugin.xml files.
+
* Performance: while small performance hit can be expected every time a new functionality is added, the performance hit should be reasonable for the "minimum" headless framework start (say < 15% ?) and should scale well.
 
+
 
+
 
+
== Details ==
+
 
+
In order to construct user-specific objects, extension registry will use constructor injection to propagate context to the objects and setter injection to propagate arguments from the plugin.xml.
+
 
+
 
+
=== Consumer-facing APIs ===
+
 
+
'''IExtensionRegistry''' will get a new method
+
 
+
<source lang="java">
+
Object[] getObjects(String path, String scope, Object context, Class ofClass)
+
</source>
+
 
+
where
+
 
+
* path: ConfEelementName1[/.../ ConfEelementName] [@attrName]
+
* scope: registry/extensionPointID[/extensionID]
+
* context: a Java object to be passed to the constructor, may be null
+
* ofClass: expected Java class of the result
+
 
+
The path will be constructed with XPath syntax in mind (although it is unlikely that full XPath will be needed).
+
The scope will be constructed with the view of potential merge of the extension registry and preferences into one mechanism
+
It is likely that multiple variations of this method will be provided to account for optional arguments, multiplicity, and typing of the result.
+
 
+
'''IExtension''' will get a new method
+
<source lang="java">
+
Object[] getObjects(Object context, Class ofType)
+
</source>
+
 
+
The extension registry will cache the objects for the duration of the session. Consumers should not cache the objects but rather feel free to ask the extension registry whenever necessary.
+
 
+
 
+
=== Provider-facing APIs ===
+
 
+
A new interface will be added:
+
<source lang="java">
+
public interface IRegistryObject {
+
public boolean init();
+
public void dispose();
+
}
+
</source>
+
 
+
On objects implementing this interface, the init() method will be called as a final step of the object creation (after all injections are processed). The displose() method will be called to indicate that the corresponding extension has been removed from the framework.
+
 
+
 
+
==== Extension point schema: class ====
+
 
+
The extension point schema will be used to pass additional information. Elements can have the Java class specified:
+
 
+
<source lang="xml">
+
<element name ="myElement">
+
<class name = "org.abc.MyClass"/>
+
</element>
+
</source>
+
 
+
The Java class specified in this way would have to have either
+
* a default no-argument constructor (if objects created from the extensions are context-free), or
+
* a single argument constructor with the type corresponding to the context (if objects are to be created in a context)
+
 
+
The "context" here is any Java object that can be passed to the extension registry at the time it is prompted for extension information.
+
 
+
''TBD consider an optional attribute multiplicity="singletonAll|singletonInContext|...".''
+
 
+
 
+
==== Default setters ====
+
 
+
The generated classes will use pre-defined method and field injection.
+
 
+
When an attribute named "abc" is found in the XML, the user class will be polled first for the method "setABC(abc.Class)" when for the field named "abc". (The method name will be case-insensitive).
+
 
+
Similar processing will be employed for the contained elements. If a sequence of elements is described in the XML, the "set…" method will be called multiple times.
+
 
+
 
+
==== Extension point schema: special setters ====
+
 
+
Several special arguments can be injected using explicit setter instructions: extension ID, extension name, extension contributor.
+
 
+
<source lang="xml">
+
<element name ="myElement">
+
<class name = "org.abc.MyClass"/>
+
<set method="setID" special="extension:id"/>
+
<set field="extensionName" special="extension: name"/>
+
</element>
+
</source>
+
 
+
The supported values are:
+
* "extension:id",
+
* "extension:name",
+
* "extension:contributor".
+
 
+
 
+
=== TBD Sateless objects vs. objects with state ===
+
 
+
<source lang="xml">
+
<element name ="myElement">
+
<class name = "org.abc.MyClass" [stateAware="true|false"]/>
+
</element>
+
</source>
+
 
+
The user-objects will be cached as soft references. As such they might be purged from the memory and re-constructed. This works fine for stateless objects. We need to investigate if there is a need for state-aware objects and, if so, add a way to specify this in the schema.
+
 
+
This would address state-aware objects for the duration of the session. Is there a need to persist such objects between sessions? ISerializable?
+
 
+
 
+
=== TBD typed values in the extension point schema ===
+
 
+
How about creating setter overrides specific to primitive types, arrays, and so on? It might save some more code (for instance, developer would not have to convert from String to int) at the expense of added complexity of the APIs.
+
 
+
 
+
=== TBD Implementation: on top of the current registry or independent? ===
+
+
The first inclanation is to do the implementation on top of the existing extension registry. However, this creates an obvious duplication in memory usage and some extra processing.
+
 
+
It might be worth while to investigate creation of an independent mechanism based on the contents of the plugin.xml. Such mechanism would avoid creation of registry artifacts altogether and only expose user-specific objects.
+
 
+
Also, for such "separate" solution an optional Java-1.5+ processing can be added where injection is done completely via constructors. (Java 1.5 gives annotations that make possible to match constructor arguments to the attributes specified in plugin.xml.) (Splitting existing registry into 1.4 and 1.5 parts won't be practical.)
+
 
+
Also, for such "separate" implementation explore if EMF helps with creating a model from XML.
+
 
+
My inclination would be to go with the "current registry + objects on top" for 3.5 stream as it is way more practical. Having this implementation in the 3.5 stream would allow us to get feedback earlier. If it goes well, we can use what we learn from 3.5 to create a "separate" implementation for 4.0 and, potentially, relegate current implementation to the compatibility layer.
+
 
+
''Pre-requisite for this item:'' get a clear understanding on caching of user objects and modified registry.
+
  
  
 
'''WORK IN PROGRESS – SUBJECT TO CHANGE'''
 
'''WORK IN PROGRESS – SUBJECT TO CHANGE'''
  
===Links===
+
== Links ==
#[http://www.martinfowler.com/articles/injection.html Inversion of Control]: "Inversion of Control Containers and the Dependency Injection pattern" by Martin Fowler
+
 
#[https://bugs.eclipse.org/bugs/show_bug.cgi?id=248340 Bug 248340]: Improve usability of the extension registry
 
#[https://bugs.eclipse.org/bugs/show_bug.cgi?id=248340 Bug 248340]: Improve usability of the extension registry
#[https://bugs.eclipse.org/bugs/show_bug.cgi?id=221603 Bug 221603]: Provide a public, reusable RegistryReader
 
 
  
 
[[Category:Equinox]]
 
[[Category:Equinox]]

Latest revision as of 13:39, 24 September 2008

WORK IN PROGRESS – SUBJECT TO CHANGE

Improving usability of the extension registry

This page tracks current state, plans, and intentions for the extension registry enhancements.

Please feel free to add comments to it.

Areas

Restrictions

  • At least for 3.x streams we need to continue supporting pre-1.5 VMs. As such, any functionality based on annotations can only be used in an optional role
  • Performance: while small performance hit can be expected every time a new functionality is added, the performance hit should be reasonable for the "minimum" headless framework start (say < 15% ?) and should scale well.


WORK IN PROGRESS – SUBJECT TO CHANGE

Links

  1. Bug 248340: Improve usability of the extension registry