Core Java

Eclipse Extension Point Evaluation Made Easy

Coding Eclipse Extension Point evaluations comes in a bit verbose and sparsely self-explaining. As I got round to busy myself with this topic recently, I wrote a little helper with the intent to reduce boilerplate code for common programming steps, while increasing development guidance and readability at the same time.

It turned out to be not that easy to find an expressive solution, which matches all the use cases I could extract from current projects. So I thought it might be a good idea to share my findings and see what other people think of it.
 
 
 

Eclipse Extension Point Evaluation

Consider a simple extension point definition that supports an unbounded contribution of extensions. Each of these contributions should provide a Runnable implementation to perform some sort of operation:

extension-point-definition

An usual evaluation task could be to retrieve all contributions, create the executable extensions and invoke each of those:

public class ContributionEvaluation {
  
  private static final String EP_ID
    = "com.codeaffine.post.contribution";

  public void evaluate() {
    IExtensionRegistry registry = Platform.getExtensionRegistry();
    IConfigurationElement[] elements
      = registry.getConfigurationElementsFor( EP_ID );
    Collection<Runnable> contributions = new ArrayList<Runnable>();
    for( IConfigurationElement element : elements ) {
      Object extension;
      try {
        extension = element.createExecutableExtension( "class" );
      } catch( CoreException e ) {
        throw new RuntimeException( e );
      }
      contributions.add( ( Runnable )extension );
    }
    for( Runnable runnable : contributions ) {
      runnable.run();
    }
  }
}

While evaluate could be split into smaller methods to clarify its responsibilities, the class would also be filled with more glue code. As I find such sections hard to read and awkward to write I was pondering about a fluent interface approach that should guide a developer through the various implementation steps.

Combined with Java 8 lambda expressions I was able to create an auxiliary that boils down the evaluate functionality to:

public void evaluate() {
  new RegistryAdapter()
    .createExecutableExtensions( EP_ID, Runnable.class )
    .withConfiguration( ( runnable, extension ) -> runnable.run() )
    .process();
}

Admittedly I cheated a bit, since it is possible to improve the first example also a little by using the java 8 Collection#forEach feature instead of looping explicitly. But I think this still would not make the code really great!

For general information on how to extend Eclipse using the extension point mechanism you might refer to the Plug-in Development Environment Guide of the online documentation.

RegistryAdapter

The main class of the helper implementation is the RegistryAdapter, which encapsulates the system’s IExtensionRegistry instance and provides a set of methods to define what operations should be performed with respect to a particular extension point. At the moment the adapter allows to read contribution configurations or to create executable extensions.

Multiple contributions are evaluated as shown above using methods that are denoted in plural – to evaluate exactly one contribution element, methods denoted in singular are appropriate. This means to operate on a particular runnable contribution you would use createExecutableExtension instead of createExecutableExtensions.

Depending on which operation is selected different configuration options are available. This is made possible as the fluent API implements a kind of grammar to improve guidance and programming safety. For example the readExtension operation does not allow to register a ExecutableExtensionConfigurator, since this would be an inept combination.

The method withConfiguration allows to configure or initialize each executable extension after its creation. But as shown in the example above it can also be used to invoke the runnable extension directly. Due to the type safe implementation of createExecutableExtension(s) it is possible to access the extension instance within the lambda expression without cast.

Finally the method process() executes the specified operation and returns a typed Collection of the created elements in case they are needed for further processing:

Collection<Extension> extensions
  = new RegistryAdapter().readExtensions( EP_ID ).process();

Predicate

But how is is possible to select a single eclipse extension point contribution element with the adapter? Assume that we add an attribute id to our contribution definition above. The fluent API of RegistryAdapter allows to specify a Predicate that can be used to select a particular contribution:

public void evaluate() {
  new RegistryAdapter()
    .createExecutableExtension( EP_ID, Runnable.class )
    .withConfiguration( ( runnable, extension ) -> runnable.run() )
    .thatMatches( attribute( "id", "myContribution" ) )
    .process();
}

There is a utility class Predicates that provides a set of predefined implementations to ease common use cases like attribute selection. The code above is a shortcut using static imports for:

.thatMatches( Predicates.attribute( "id", "myContribution" ) )

where “myContribution” stands for the unique id value declared in the extension contribution:

<extension point="com.codeaffine.post.contribution">
  <contribution id="myContribution" class="com.codeaffine.post.MyContribution">
  </contribution>
</extension>

Of course it is possible to implement custom predicates in case the presets are not sufficient:

public void evaluate() {
  Collection<Extension> extensions = new RegistryAdapter()
    .readExtensions( EP_ID, Description.class )
    .thatMatches( (extension) -> extension.getValue() != null )
    .process();
}

Extension

Usually Eclipse Extension Point evaluation operates most of the time on IConfigurationElement. The adapter API is unsharp in distinguishing between extension point and configuration element and provides a simple encapsulation called Extension. But for more sophisticated tasks Extension instances make the underlying configuration element accessible.

In general Extension provides accessors to the attribute values, contribution names, contribution values, nested contributions and allows to create an executable extension. One of the major reasons to introduce this abstraction was to have an API that converts checked CoreException implicitly to runtime exceptions as I am accustomed to work with the Fail Fast approach without bulky checked exeption handling.

Exception Handling

However in case that the eclipse extension evaluation is invoked at startup time of a plug-in or gets executed in background, Fail Fast is not an option. And it is surely not reasonable to ignore remaining contributions after a particular contribution has caused a problem. Because of this the adapter API allows to replace the Fail Fast mechanism with explicit exception handling:

public void evaluate() {
  Collection<Runnable> contributions = new RegistryAdapter()
    .createExecutableExtensions( EP_ID, Runnable.class )
    .withExceptionHandler( (cause) -> handle( cause ) )
    .process();
    
  [...]
}
  
private void handle( CoreException cause ) {
  // do what you gotta do
}

Note that the returned collection of contributions contains of course only those elements that did not run into any trouble.

Where to get it?

For those who want to check it out, there is a P2 repository that contains the feature com.codeaffine.eclipse.core.runtime providing the RegistryAdapter and its accompanying classes. The repository is located at:

and the source code and issue tracker is hosted at:

Although documentation is missing completely at this moment, it should be quite easy to get started with the given explanations of this post. But please keep in mind that the little tool is in a very early state and probably will undergo some API changes. In particular dealing only with CoreExceptions while looping over the contributions still is a bit too weak.

Conclusion

The sections above introduced the basic functionality of the RegistyAdapter and focused on how it eases Eclipse extension point evaluation. I replaced old implementations in my current projects with the adapter and did not run into any trouble, which means that the solution looks promising to me so far…

But there is still more than meets the eye. With this little helper in place, combined with an additional custom assert type, writing integration tests for an extension point’s evaluation functionality really gets a piece of cake.

That topic is however out of scope for this post and will be covered next time. So stay tuned and do not forget to share the knowledge, in case you find the approach described above useful – thanks!

Reference: Eclipse Extension Point Evaluation Made Easy from our JCG partner Rudiger Herrmann at the Code Affine blog.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button