Bug 520080 - Provide convenient image handling facilities for activator-less bundles
Summary: Provide convenient image handling facilities for activator-less bundles
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.8   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 4.13 M1   Edit
Assignee: Alexander Fedorov CLA
QA Contact:
URL:
Whiteboard:
Keywords: noteworthy
Depends on:
Blocks: 549861
  Show dependency tree
 
Reported: 2017-07-24 03:25 EDT by Matthias Becker CLA
Modified: 2019-08-14 05:23 EDT (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthias Becker CLA 2017-07-24 03:25:32 EDT
In the course of bugs 516114 and 516738 I got aware of http://blog.vogella.com/2015/09/16/eclipse-activator-startup-sins-tracing-the-startup-time/

When you try to get rid of existing activators you often find activators that use AbstractUIPlugin's image managing facilities (the initializeImageRegistry, getImageRegistry, .. methods). Populating an image registry can also be done in other classes it does not necessarily happen in bundle activators. 

The fact that the AbstractUIPlugin does provide such convenient methods to easily manager your images and that there is no other class in eclipse platform that provides comparable convenience is the cause that a lot of bundles register their images in their activators.

So I propose to extract that image handling stuff out of AbstractUIPlugin. With that we have a clearer separation of concerns and activator-less bundles also can use this.
Comment 1 Eclipse Genie CLA 2017-07-24 03:26:54 EDT
New Gerrit change created: https://git.eclipse.org/r/101785
Comment 2 Matthias Becker CLA 2017-07-24 03:28:01 EDT
May change does multiple things:

1) Create new class AbstractImageMager
Most of the code is simply copied over from AbstractUIPlugin. I also adds the methods registerImage that simply registers an image descriptor from a given file name.
Name of the class and especially it's location are only a first prototype. I am open to better ideas.

2) Use org.eclipse.ui.forms.examples to show how to use the new class.

3) Removes the code in AbstractUIPlugin's image handling methods and replaces them by delegation to the new class. This is done to avoid duplicated code.

What's your opinion with regards to that change?
Comment 3 Dirk Fauth CLA 2017-07-24 04:18:15 EDT
Is JFaceResources#getImageRegistry() not sufficient as a replacement?
Comment 4 Matthias Becker CLA 2017-07-24 04:21:32 EDT
(In reply to Dirk Fauth from comment #3)
> Is JFaceResources#getImageRegistry() not sufficient as a replacement?

As this is static all plugins would put their images into the one and only registry.
I think it's a good idea to keep images from different bundles separated from each other.
Comment 5 Lars Vogel CLA 2017-07-24 06:46:56 EDT
(In reply to Matthias Becker from comment #2)
> What's your opinion with regards to that change?

I like the idea but "org.eclipse.ui.workbench" is too high in the stack. I suggest extending JFace with the option to create an image registry based on key. Bundles could use that to provide the bundle-symbolic-name as key.
Comment 6 Matthias Becker CLA 2017-07-24 06:49:51 EDT
(In reply to Lars Vogel from comment #5)
> (In reply to Matthias Becker from comment #2)
> > What's your opinion with regards to that change?
> 
> I like the idea but "org.eclipse.ui.workbench" is too high in the stack.
Sure. I just needed to put it somewhere.
Comment 7 Matthias Becker CLA 2017-07-24 06:51:40 EDT
(In reply to Lars Vogel from comment #5)
> I suggest extending JFace with the option to create an image registry based on
> key. Bundles could use that to provide the bundle-symbolic-name as key.

Can you explain in more detail what exactly you have in mind?
Comment 8 Lars Vogel CLA 2017-07-24 07:02:49 EDT
(In reply to Matthias Becker from comment #7)
> (In reply to Lars Vogel from comment #5)
> > I suggest extending JFace with the option to create an image registry based on
> > key. Bundles could use that to provide the bundle-symbolic-name as key.
> 
> Can you explain in more detail what exactly you have in mind?

Something like JFaceResources#getImageRegistry(String keyForRegistry). Consumers could use it, for example with 

String bundleSymbolicName = FrameworkUtil.getBundle(this.getClass()).getSymbolicName();
JFaceResources#getImageRegistry(bundleSymbolicName)
Comment 9 Matthias Becker CLA 2017-07-25 08:21:39 EDT
(In reply to Lars Vogel from comment #8)
> (In reply to Matthias Becker from comment #7)
> > (In reply to Lars Vogel from comment #5)
> > > I suggest extending JFace with the option to create an image registry based on
> > > key. Bundles could use that to provide the bundle-symbolic-name as key.
> > 
> > Can you explain in more detail what exactly you have in mind?
> 
> Something like JFaceResources#getImageRegistry(String keyForRegistry).
> Consumers could use it, for example with 
> 
> String bundleSymbolicName =
> FrameworkUtil.getBundle(this.getClass()).getSymbolicName();
> JFaceResources#getImageRegistry(bundleSymbolicName)

OK. I thought about this. 

Your proposal does only address the createImageRegistry method of AbstractImageManager. But my solution provides much more then the creation of an image registry. My proposal: 
- ensures that one consumer only registers their images
- provide easy to use lazy-registration (via the initializeImageRegistry method).
- is may more explicit. So it's easier for consumers to understand how to use it

In my option the task of JFaceResources is to provide access to shared stuff (see especially the initializeDefaultImages method). My solution is focused on plugin specific / consumer specific images.

So I don't see the advantage of JFaceResources#getImageRegistry(bundleSymbolicName).
Comment 10 Dirk Fauth CLA 2017-07-25 10:47:49 EDT
I'm unsure about your solution. For example, why is it in org.eclipse.ui which is Eclipse 3.x? In the end you provide a wrapper for registering images to a plugin local registry instance. And where is that instance kept? The previous solution was to hold the reference in the Activator.
Comment 11 Matthias Becker CLA 2017-07-25 10:51:39 EDT
(In reply to Dirk Fauth from comment #10)
> I'm unsure about your solution. For example, why is it in org.eclipse.ui
> which is Eclipse 3.x? In the end you provide a wrapper for registering
> images to a plugin local registry instance.

Don't get confused by the location. It should go into JFace. I first wanted to discuss this topic before I start to add something to JFace.

> And where is that instance kept?
It's kept in a static member. An example can be found in  ExamplesImages#INSTANCE.

> The previous solution was to hold the reference in the Activator.
The point of my solution is to have a solution when you don't have an Activator / if you want to get rid of your activator.
Comment 12 Thomas Schindl CLA 2017-07-25 11:03:19 EDT
I agree with Dirk that the proposed solution is not a good idea. I just glanced over the code and the first problem I came across is that you cache the managers in a static map. 

How do you clean up the map when the bundle is going down? If i read the code correct you produce not only an (image) handle leak but also a classloader leak.
Comment 13 Matthias Becker CLA 2017-07-26 02:04:47 EDT
(In reply to Thomas Schindl from comment #12)
> I agree with Dirk that the proposed solution is not a good idea. I just
> glanced over the code and the first problem I came across is that you cache
> the managers in a static map. 

Understood. This was my attempt to inhibit that a consumer (by accident creates multiple instances of his subclass. We can remove that part - it's not a vital part of my solution. Do you have an alternative solution for inhibiting this multiple instanciation?


> How do you clean up the map when the bundle is going down? If i read the
> code correct you produce not only an (image) handle leak but also a
> classloader leak.

Good point. I provided a dispose method to clean up the images in the registry. But to call that when the bundle is goind down you have to call in the stop() method of your activator. But if you don't have one / want to get rid of your activator I don't know how to do it. Is there another mechanism how a bundle get's notified that it's going to be stopped?
Comment 14 Mikaël Barbero CLA 2017-07-26 04:11:41 EDT
What about just using declarative services? This way, the component will follow the bundle lifecycle, you could still init on the first call on getImageRegistry, and dispose when the component is being deactivated. You may need to introduce an interface for your AbstractImageManager. Alas, it means it needs to stay somewhere in org.eclipse.ui and not in jface.
Comment 15 Lars Vogel CLA 2019-06-24 05:21:09 EDT
Maybe we should simply pull out the AbstractUIPlugin#imageDescriptorFromPlugin into a utility class?

This would for example allow to replace the activator usage of org.eclipse.ui.tests.views.properties.tabbed.

Gerrit upcoming for discussion.
Comment 16 Eclipse Genie CLA 2019-06-24 05:23:13 EDT
New Gerrit change created: https://git.eclipse.org/r/144705
Comment 17 Eclipse Genie CLA 2019-06-25 15:06:57 EDT
New Gerrit change created: https://git.eclipse.org/r/144873
Comment 19 Lars Vogel CLA 2019-06-30 07:55:30 EDT
Thanks, Alexander. Please add to N&N
Comment 20 Eclipse Genie CLA 2019-08-08 06:13:40 EDT
New Gerrit change created: https://git.eclipse.org/r/147251