Skip to content

Commit

Permalink
Use OSGi service for UI startup handler
Browse files Browse the repository at this point in the history
Bundle activators should do as little work as possible. Therefore move
the registration of the window listener out of the bundle activation and
instead have OSGi call back when the application has started. That's
later, that improves startup performance and that should avoid race
conditions on the workbench access.
  • Loading branch information
Bananeweizen authored and Calixte committed Jan 9, 2025
1 parent 694ca5c commit a7be71c
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 94 deletions.
5 changes: 5 additions & 0 deletions net.sf.eclipsecs.ui/.project
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.pde.ds.core.builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
dsVersion=V1_3
eclipse.preferences.version=1
enabled=true
generateBundleActivationPolicyLazy=true
path=OSGI-INF
validationErrorLevel=error
validationErrorLevel.missingImplicitUnbindMethod=error
5 changes: 4 additions & 1 deletion net.sf.eclipsecs.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ Require-Bundle: net.sf.eclipsecs.core,
org.eclipse.core.expressions,
org.eclipse.ui.workbench,
org.eclipse.jface,
org.eclipse.help;bundle-version="3.9.0"
org.eclipse.help;bundle-version="3.9.0",
org.eclipse.e4.ui.workbench;bundle-version="1.13.200"
Service-Component: OSGI-INF/net.sf.eclipsecs.ui.ApplicationStartedHandler.xml
Bundle-RequiredExecutionEnvironment: JavaSE-17
Export-Package: net.sf.eclipsecs.ui,
net.sf.eclipsecs.ui.properties.filter,
Expand Down Expand Up @@ -66,6 +68,7 @@ Import-Package: org.apache.commons.lang3;version="3.12.0",
org.eclipse.ui.texteditor,
org.eclipse.ui.views.markers,
org.osgi.framework,
org.osgi.service.event;version="[1.4.0,2.0.0)",
org.osgi.service.prefs
Automatic-Module-Name: net.sf.eclipsecs.ui

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="net.sf.eclipsecs.ui.ApplicationStartedHandler">
<property name="event.topics" value="org/eclipse/e4/ui/LifeCycle/appStartupComplete"/>
<service>
<provide interface="org.osgi.service.event.EventHandler"/>
</service>
<implementation class="net.sf.eclipsecs.ui.ApplicationStartedHandler"/>
</scr:component>
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
//============================================================================
//
// Copyright (C) 2003-2023 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
//
//============================================================================

package net.sf.eclipsecs.ui;

import org.osgi.service.component.annotations.Component;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;

import net.sf.eclipsecs.core.jobs.AbstractCheckJob;
import net.sf.eclipsecs.ui.properties.filter.CheckFileOnOpenPartListener;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;

import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;

/**
* Event handler being called when the eclipse application has started.
*/
@Component(property = EventConstants.EVENT_TOPIC + "=" + UIEvents.UILifeCycle.APP_STARTUP_COMPLETE)
public class ApplicationStartedHandler implements EventHandler {

private final CheckFileOnOpenPartListener mPartListener = new CheckFileOnOpenPartListener();

private final IWindowListener mWindowListener = new IWindowListener() {

@Override
public void windowOpened(IWorkbenchWindow window) {
window.getPartService().addPartListener(mPartListener);
}

@Override
public void windowActivated(IWorkbenchWindow window) {
}

@Override
public void windowClosed(IWorkbenchWindow window) {
window.getPartService().removePartListener(mPartListener);

}

@Override
public void windowDeactivated(IWorkbenchWindow window) {
}

};

@Override
public void handleEvent(org.osgi.service.event.Event event) {
if (!UIEvents.UILifeCycle.APP_STARTUP_COMPLETE.equals(event.getTopic())) {
return;
}
registerListener();
registerProgressIcon();
}

private void registerListener() {
// add listeners for the Check-On-Open support
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {

IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();

for (IWorkbenchWindow window : windows) {

if (window != null) {

// collect open editors and have then run against Checkstyle if
// appropriate
Collection<IWorkbenchPartReference> parts = new HashSet<>();

// add already opened files to the filter
// bugfix for 2923044
IWorkbenchPage[] pages = window.getPages();
for (IWorkbenchPage page : pages) {

IEditorReference[] editorRefs = page.getEditorReferences();
Collections.addAll(parts, editorRefs);
}

mPartListener.partsOpened(parts);

// remove listener first for safety, we don't want
// register the same listener twice accidently
window.getPartService().removePartListener(mPartListener);
window.getPartService().addPartListener(mPartListener);
}
}

workbench.addWindowListener(mWindowListener);
}
});
}

protected void registerProgressIcon() {
IProgressService service = PlatformUI.getWorkbench().getProgressService();
if (service == null) {
return;
}
service.registerIconForFamily(CheckstyleUIPluginImages.CHECKSTYLE_ICON.getImageDescriptor(),
AbstractCheckJob.CHECKSTYLE_JOB_FAMILY);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@

package net.sf.eclipsecs.ui;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Locale;

import org.eclipse.core.resources.IWorkspace;
Expand All @@ -33,20 +30,10 @@
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.progress.IProgressService;
import org.osgi.framework.BundleContext;

import net.sf.eclipsecs.core.jobs.AbstractCheckJob;
import net.sf.eclipsecs.core.util.CheckstyleLog;
import net.sf.eclipsecs.ui.properties.filter.CheckFileOnOpenPartListener;

/**
* The main plugin class to be used in the desktop.
Expand All @@ -61,95 +48,15 @@ public class CheckstyleUIPlugin extends AbstractUIPlugin {

private static Boolean isEclipse3;

private final CheckFileOnOpenPartListener mPartListener = new CheckFileOnOpenPartListener();

private final IWindowListener mWindowListener = new IWindowListener() {

@Override
public void windowOpened(IWorkbenchWindow window) {
window.getPartService().addPartListener(mPartListener);
}

@Override
public void windowActivated(IWorkbenchWindow window) {
}

@Override
public void windowClosed(IWorkbenchWindow window) {
window.getPartService().removePartListener(mPartListener);

}

@Override
public void windowDeactivated(IWorkbenchWindow window) {
}

};

/**
* The constructor.
*/
public CheckstyleUIPlugin() {
sPlugin = this;
}

@Override
public void start(BundleContext context) throws Exception {
super.start(context);

// add listeners for the Check-On-Open support
final IWorkbench workbench = PlatformUI.getWorkbench();
workbench.getDisplay().asyncExec(new Runnable() {
@Override
public void run() {

IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();

for (IWorkbenchWindow window : windows) {

if (window != null) {

// collect open editors and have then run against Checkstyle if
// appropriate
Collection<IWorkbenchPartReference> parts = new HashSet<>();

// add already opened files to the filter
// bugfix for 2923044
IWorkbenchPage[] pages = window.getPages();
for (IWorkbenchPage page : pages) {

IEditorReference[] editorRefs = page.getEditorReferences();
Collections.addAll(parts, editorRefs);
}

mPartListener.partsOpened(parts);

// remove listener first for safety, we don't want
// register the same listener twice accidently
window.getPartService().removePartListener(mPartListener);
window.getPartService().addPartListener(mPartListener);
}
}

workbench.addWindowListener(mWindowListener);
registerProgressIcon();
}
});

}

protected void registerProgressIcon() {
IProgressService service = PlatformUI.getWorkbench().getProgressService();
if (service == null) {
return;
}
service.registerIconForFamily(CheckstyleUIPluginImages.CHECKSTYLE_ICON.getImageDescriptor(),
AbstractCheckJob.CHECKSTYLE_JOB_FAMILY);
}

@Override
public void stop(BundleContext context) throws Exception {

// free cached images
CheckstyleUIPluginImages.clearCachedImages();
super.stop(context);
Expand Down

0 comments on commit a7be71c

Please sign in to comment.