Skip to content

Commit

Permalink
Provide TARGET_SAVED and TARGET_DELETED events
Browse files Browse the repository at this point in the history
When building tools on top of PDE's target platform framework it's
often necessary to be informed about state changes in targets. PDE
already uses an IEventBroker to send "workspaceTargetChanged" events.
This change is about sending two new events:
TARGET_SAVED and TARGET_DELETED
  • Loading branch information
estepper authored and HannesWell committed Nov 9, 2024
1 parent ee1f4a3 commit 5856baf
Show file tree
Hide file tree
Showing 9 changed files with 179 additions and 22 deletions.
22 changes: 22 additions & 0 deletions ui/org.eclipse.pde.core/.settings/.api_filters
Original file line number Diff line number Diff line change
@@ -1,5 +1,27 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<component id="org.eclipse.pde.core" version="2">
<resource path="META-INF/MANIFEST.MF">
<filter id="926941240">
<message_arguments>
<message_argument value="3.20.0"/>
<message_argument value="3.19.0"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/pde/core/target/TargetEvents.java" type="org.eclipse.pde.core.target.TargetEvents">
<filter id="336658481">
<message_arguments>
<message_argument value="org.eclipse.pde.core.target.TargetEvents"/>
<message_argument value="TOPIC_TARGET_DELETED"/>
</message_arguments>
</filter>
<filter id="336658481">
<message_arguments>
<message_argument value="org.eclipse.pde.core.target.TargetEvents"/>
<message_argument value="TOPIC_TARGET_SAVED"/>
</message_arguments>
</filter>
</resource>
<resource path="src/org/eclipse/pde/internal/core/project/BundleProjectService.java" type="org.eclipse.pde.internal.core.project.BundleProjectService">
<filter comment="Platform Team allows use of bundle importers for PDE import from source repository" id="640712815">
<message_arguments>
Expand Down
3 changes: 2 additions & 1 deletion ui/org.eclipse.pde.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %name
Bundle-SymbolicName: org.eclipse.pde.core; singleton:=true
Bundle-Version: 3.19.100.qualifier
Bundle-Version: 3.20.0.qualifier
Bundle-Activator: org.eclipse.pde.internal.core.PDECore
Bundle-Vendor: %provider-name
Bundle-Localization: plugin
Expand Down Expand Up @@ -101,6 +101,7 @@ Import-Package: aQute.bnd.build;version="[4.4.0,5.0.0)",
org.eclipse.equinox.internal.p2.publisher.eclipse,
org.eclipse.equinox.p2.publisher,
org.eclipse.equinox.p2.publisher.eclipse,
org.osgi.service.event;version="[1.4.0,2.0.0)";resolution:=optional,
org.osgi.service.repository;version="[1.1.0,2.0.0)",
org.osgi.util.promise;version="[1.3.0,2.0.0)"
Require-Bundle:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,119 @@
********************************************************************************/
package org.eclipse.pde.core.target;

import org.eclipse.e4.core.services.events.IEventBroker;
import org.osgi.service.event.EventHandler;

/**
* Target events and event topic definitions
* Target events and event topic definitions. Can be used as follows:
*
* <pre>
* EventHandler eventHandler = event -> {
* Object data = event.getProperty(IEventBroker.DATA);
* if (data instanceof ITargetHandle) {
* ITargetHandle handle = (ITargetHandle) data;
* // Work with the target handle...
* }
* };
*
* IEclipseContext context = EclipseContextFactory.getServiceContext(bundleContext);
* IEventBroker broker = context.get(IEventBroker.class);
* if (broker != null) {
* broker.subscribe(TargetEvents.TOPIC_TARGET_SAVED, eventHandler);
* // Do not forget to unsubscribe later!
* }
* </pre>
*
* @see ITargetPlatformService
* @see IEventBroker#subscribe(String, EventHandler)
* @see IEventBroker#subscribe(String, String, EventHandler, boolean)
* @see IEventBroker#unsubscribe(EventHandler)
* @since 3.13
*/
public class TargetEvents {

/**
* Base topic for all Target events
* Base topic for all target events.
*/
public static final String TOPIC_BASE = "org/eclipse/pde/core/target/TargetEvents"; //$NON-NLS-1$

/**
* Topic for all Target events
* Topic for all target events.
*/
public static final String TOPIC_ALL = TOPIC_BASE + "/*"; //$NON-NLS-1$

/**
* Sent when workspace target definition is changed
* Sent when workspace target definition is changed. Can be used as follows:
*
* <pre>
* EventHandler eventHandler = event -> {
* Object data = event.getProperty(IEventBroker.DATA);
* if (data instanceof ITargetDefinition) {
* ITargetDefinition definition = (ITargetDefinition) data;
* // Work with the target definition...
* }
* };
*
* IEclipseContext context = EclipseContextFactory.getServiceContext(bundleContext);
* IEventBroker broker = context.get(IEventBroker.class);
* if (broker != null) {
* broker.subscribe(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, eventHandler);
* // Do not forget to unsubscribe later!
* }
* </pre>
*
* @see ITargetPlatformService#getWorkspaceTargetDefinition()
*/
public static final String TOPIC_WORKSPACE_TARGET_CHANGED = TOPIC_BASE + "/workspaceTargetChanged"; //$NON-NLS-1$

/**
* Sent when a target is saved. Can be used as follows:
*
* <pre>
* EventHandler eventHandler = event -> {
* Object data = event.getProperty(IEventBroker.DATA);
* if (data instanceof ITargetHandle) {
* ITargetHandle handle = (ITargetHandle) data;
* // Work with the target handle...
* }
* };
*
* IEclipseContext context = EclipseContextFactory.getServiceContext(bundleContext);
* IEventBroker broker = context.get(IEventBroker.class);
* if (broker != null) {
* broker.subscribe(TargetEvents.TOPIC_TARGET_SAVED, eventHandler);
* // Do not forget to unsubscribe later!
* }
* </pre>
*
* @see ITargetPlatformService#saveTargetDefinition(ITargetDefinition)
* @see IEventBroker
* @since 3.20
*/
public static final String TOPIC_TARGET_SAVED = TOPIC_BASE + "/targetSaved"; //$NON-NLS-1$

/**
* Sent when a target is deleted. Can be used as follows:
*
* <pre>
* EventHandler eventHandler = event -> {
* Object data = event.getProperty(IEventBroker.DATA);
* if (data instanceof ITargetHandle) {
* ITargetHandle handle = (ITargetHandle) data;
* // Work with the target handle...
* }
* };
*
* IEclipseContext context = EclipseContextFactory.getServiceContext(bundleContext);
* IEventBroker broker = context.get(IEventBroker.class);
* if (broker != null) {
* broker.subscribe(TargetEvents.TOPIC_TARGET_DELETED, eventHandler);
* // Do not forget to unsubscribe later!
* }
* </pre>
*
* @see ITargetPlatformService#deleteTarget(ITargetHandle)
* @since 3.20
*/
public static final String TOPIC_TARGET_DELETED = TOPIC_BASE + "/targetDeleted"; //$NON-NLS-1$
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetHandle;
import org.eclipse.pde.core.target.TargetEvents;

/**
* Common implementation of target handles.
Expand Down Expand Up @@ -53,11 +54,18 @@ public ITargetDefinition getTargetDefinition() throws CoreException {
*/
abstract void delete() throws CoreException;

public final void save(ITargetDefinition definition) throws CoreException {
doSave(definition);

TargetPlatformService service = (TargetPlatformService) TargetPlatformService.getDefault();
service.scheduleEvent(TargetEvents.TOPIC_TARGET_SAVED, definition.getHandle());
}

/**
* Saves the definition to underlying storage.
*
* @param definition target to save
* @throws CoreException on failure
*/
abstract void save(ITargetDefinition definition) throws CoreException;
abstract void doSave(ITargetDefinition definition) throws CoreException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ protected InputStream getInputStream() throws CoreException {


@Override
void save(ITargetDefinition definition) throws CoreException {
void doSave(ITargetDefinition definition) throws CoreException {
try (OutputStream stream = new BufferedOutputStream(new FileOutputStream(fFile))) {
((TargetDefinition) definition).write(stream);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ protected OutputStream getOutputStream() throws CoreException {
}

@Override
void save(ITargetDefinition definition) throws CoreException {
void doSave(ITargetDefinition definition) throws CoreException {
try (OutputStream stream = getOutputStream()) {
((TargetDefinition) definition).write(stream);
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
import org.eclipse.pde.internal.core.TargetDefinitionManager;
import org.eclipse.pde.internal.core.TargetPlatformHelper;
import org.eclipse.pde.internal.core.target.IUBundleContainer.UnitDeclaration;
import org.osgi.framework.BundleContext;
import org.osgi.service.prefs.BackingStoreException;

/**
Expand Down Expand Up @@ -160,6 +161,7 @@ public void deleteTarget(ITargetHandle handle) throws CoreException {
}
((AbstractTargetHandle) handle).delete();
TargetPlatformHelper.getTargetDefinitionMap().remove(handle);
scheduleEvent(TargetEvents.TOPIC_TARGET_DELETED, handle);
}

@Override
Expand Down Expand Up @@ -305,7 +307,8 @@ public ITargetDefinition newTarget() {

@Override
public void saveTargetDefinition(ITargetDefinition definition) throws CoreException {
((AbstractTargetHandle) definition.getHandle()).save(definition);
ITargetHandle handle = definition.getHandle();
((AbstractTargetHandle) handle).save(definition);
}

@Override
Expand Down Expand Up @@ -364,24 +367,30 @@ public void setWorkspaceTargetDefinition(ITargetDefinition target, boolean async
boolean changed = !Objects.equals(oldTarget, target);
if (changed) {
if (asyncEvents) {
eventSendingJob.schedule(target);
scheduleEvent(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, target);
} else {
notifyTargetChanged(target);
notifyEvent(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, target);
}
}
}

static void notifyTargetChanged(ITargetDefinition target) {
IEclipseContext context = EclipseContextFactory.getServiceContext(PDECore.getDefault().getBundleContext());
public final void scheduleEvent(String topic, Object data) {
eventSendingJob.schedule(topic, data);
}

private static void notifyEvent(String topic, Object data) {
BundleContext bundleContext = PDECore.getDefault().getBundleContext();
IEclipseContext context = EclipseContextFactory.getServiceContext(bundleContext);

IEventBroker broker = context.get(IEventBroker.class);
if (broker != null) {
broker.send(TargetEvents.TOPIC_WORKSPACE_TARGET_CHANGED, target);
broker.send(topic, data);
}
}

static class EventDispatcher extends Job {
private static final class EventDispatcher extends Job {

private final ConcurrentLinkedQueue<ITargetDefinition> queue;
private final ConcurrentLinkedQueue<EventInfo> queue;
private final Object myFamily;

/**
Expand All @@ -405,9 +414,9 @@ public boolean belongsTo(Object family) {

@Override
protected IStatus run(IProgressMonitor monitor) {
ITargetDefinition target;
while ((target = queue.poll()) != null && !monitor.isCanceled()) {
notifyTargetChanged(target);
EventInfo eventInfo;
while ((eventInfo = queue.poll()) != null && !monitor.isCanceled()) {
notifyEvent(eventInfo.topic, eventInfo.data);
}
if (!queue.isEmpty() && !monitor.isCanceled()) {
// in case actions got faster scheduled then processed
Expand All @@ -423,10 +432,20 @@ protected IStatus run(IProgressMonitor monitor) {
/**
* Enqueue a task asynchronously.
**/
public void schedule(ITargetDefinition target) {
queue.offer(target);
public void schedule(String topic, Object data) {
queue.offer(new EventInfo(topic, data));
schedule(); // will reschedule if already running
}

private static final class EventInfo {
final String topic;
final Object data;

EventInfo(String topic, Object data) {
this.topic = topic;
this.data = data;
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public String getMemento() throws CoreException {
}

@Override
public void save(ITargetDefinition definition) throws CoreException {
void doSave(ITargetDefinition definition) throws CoreException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
((TargetDefinition) definition).write(outputStream);
ByteArrayInputStream stream = new ByteArrayInputStream(outputStream.toByteArray());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
import org.eclipse.pde.internal.core.PDEPreferencesManager;
import org.eclipse.pde.internal.core.target.P2TargetUtils;
import org.eclipse.pde.internal.core.target.TargetDefinitionPersistenceHelper;
import org.eclipse.pde.internal.core.target.TargetPlatformService;
import org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle;
import org.eclipse.pde.internal.ui.IHelpContextIds;
import org.eclipse.pde.internal.ui.PDEPlugin;
Expand Down Expand Up @@ -175,6 +176,7 @@ protected void pageChange(int newPageIndex) {

@Override
public void doSave(IProgressMonitor monitor) {
ITargetHandle handle = fInputHandler.getTarget().getHandle();
fInputHandler.setSaving(true);
if (!isActiveTabTextualEditor()) {
markStale();
Expand All @@ -184,6 +186,9 @@ public void doSave(IProgressMonitor monitor) {
fDirty = false;
editorDirtyStateChanged();
fInputHandler.setSaving(false);

TargetPlatformService service = (TargetPlatformService) TargetPlatformService.getDefault();
service.scheduleEvent(TargetEvents.TOPIC_TARGET_SAVED, handle);
}

@Override
Expand Down Expand Up @@ -286,6 +291,17 @@ public void dispose() {
super.dispose();
}

@Override
public <T> T getAdapter(Class<T> adapter) {
if (adapter.equals(ITargetHandle.class)) {
ITargetDefinition target = getTarget();
if (target != null) {
return adapter.cast(target.getHandle());
}
}

return super.getAdapter(adapter);
}
/**
* Returns the target model backing this editor
* @return target model
Expand Down

0 comments on commit 5856baf

Please sign in to comment.