Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the IEclipseContext in an activator

I got stuck on one problem with an Eclipse 4 RCP application. I need to log some events. I need obtain somehow a reference to the logger. I know, how to do that using IEclipseContext, but I've nowhere found, how to obtain IEclipseContext without the dependency injection, which I cannot use in the activator. Do you anybody know, how to sort it out this problem, please?

Thanks a lot

like image 672
Theodor Keinstein Avatar asked Aug 19 '13 14:08

Theodor Keinstein


3 Answers

You can get a specialized IEclipseContext by calling EclipseContextFactory.getServiceContext(bundleContext) which will allow access to OSGi services.

like image 139
greg-449 Avatar answered Nov 13 '22 18:11

greg-449


It seems regretably, that there is no way to obtain IEclipseContext without using injection. There is written in an answer to How to use eclipse 4 DI in classes that are not attached to the application model:

The problem is, however, that the IEclipseContext already needs to be injected into a class that can access the object that needs injection.

Nevertheless I have already sorted out the problem of logging and I thing, the principle works generally. There is always some service providing things you need. If you cannot use the dependency injection, you've to get somehow (Internet and experiments are very often) an appropriate service class name. If you have got the service class name, then you can obtain an instance reference from the bundle context. Fortunately, the bundle context is accessible without using injection.

Back to our logging problem. The class being searched is org.osgi.service.log.LogService:

public class Activator implements BundleActivator {
    ...
    private static BundleContext context;
    ...

    public static BundleContext getContext() {
        return context;
    }
    ...
    public void start(BundleContext bundleContext) throws Exception {
        ServiceReference<?> logser = bundleContext.getServiceReference(LogService.class);
        LogService ls = (LogService)bundleContext.getService(logser);
        //print an error to test it (note, that info can be below the threshold)
        ls.log(LogService.LOG_ERROR, "The bundle is starting...");
        Activator.context = bundleContext;
    }
    ...
}

Et voilà!

!ENTRY eu.barbucha.rcp-experiment.kernel 4 0 2013-08-20 07:32:32.347
!MESSAGE The bundle is starting...

That's all. Later you can obtain the bundle context using Activator.getContext(), if it would be needed.

Important note: Regretably you cannot decrease the threshold now. The JVM argument -Declipse.log.level does not affect the OSGI log service and you're using just the OSGI logger now. Unfortunately they (may have provisionally) hardcoded the logging threshold (see How to log warnings and infos in eclipse 3.7). I found out, that they haven't repair it yet. Neither in the Kepler release. However you can make a compromise. You can do that injection-way, where possible.

Final solution (to catch exceptions globally as well)

I extended my activator:

ServiceReference<?> logreser = bundleContext.getServiceReference(LogReaderService.class);
LogReaderService lrs = (LogReaderService) bundleContext.getService(logreser);   
lrs.addLogListener(new LogListener() {
    @Override
    public void logged(LogEntry entry) {
        System.err.println("Something was logged: " + entry.getMessage());
    }
});

The text beginning with Something was logged really appears, whenewer is something somewhere logged. But the very advantage is, that this class is mine. I can control it. The log entry contains also the level. I can also easily set the threshold. For example on the command line.

like image 36
Theodor Keinstein Avatar answered Nov 13 '22 20:11

Theodor Keinstein


It is possible to get the "WorkbenchContext" from the IWorkbench as a service:

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.ui.PlatformUI;

public final class EclipseContextHelper {

    public static IEclipseContext getActiveContext(){
        IEclipseContext context = getWorkbenchContext();
        return context == null ? null : context.getActiveLeaf();
    }

    public static IEclipseContext getWorkbenchContext(){
        return PlatformUI.getWorkbench().getService(IEclipseContext.class);
    }
}
like image 2
Balder Avatar answered Nov 13 '22 19:11

Balder