blob: 6fdfe1c882309a3abe658fb9628eae86f55db0d8 [file] [log] [blame]
package org.eclipse.rap.e4.internal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import javax.inject.Named;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.core.services.log.Logger;
import org.eclipse.e4.ui.di.UISynchronize;
import org.eclipse.e4.ui.internal.workbench.swt.E4Application;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.workbench.IWorkbench;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
public class RAPEventBroker implements IEventBroker {
// TBD synchronization
private static final String ASYNC_EVENT = "rap.async.event";
private Map<EventHandler, Collection<ServiceRegistration<?>>> registrations = new HashMap<EventHandler, Collection<ServiceRegistration<?>>>();
@Inject
Logger logger;
@Inject
@Optional
UISynchronize uiSync;
@Inject
@Named(E4Application.INSTANCEID)
String instanceId;
// This is a temporary code to ensure that bundle containing
// EventAdmin implementation is started. This code it to be removed once
// the proper method to start EventAdmin is added.
static {
EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
if (eventAdmin == null) {
Bundle[] bundles = Activator.getDefault().getBundleContext().getBundles();
for (Bundle bundle : bundles) {
if (!"org.eclipse.equinox.event".equals(bundle.getSymbolicName()))
continue;
try {
bundle.start(Bundle.START_TRANSIENT);
} catch (BundleException e) {
e.printStackTrace();
}
break;
}
}
}
public RAPEventBroker() {
// placeholder
}
public boolean send(String topic, Object data) {
Event event = constructEvent(topic, data, false);
EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
if (eventAdmin == null) {
logger.error(NLS.bind("No EventAdmin", event.toString()));
return false;
}
eventAdmin.sendEvent(event);
return true;
}
public boolean post(String topic, Object data) {
Event event = constructEvent(topic, data, true);
EventAdmin eventAdmin = Activator.getDefault().getEventAdmin();
if (eventAdmin == null) {
logger.error(NLS.bind("No EventAdmin", event.toString()));
return false;
}
eventAdmin.postEvent(event);
return true;
}
@SuppressWarnings("unchecked")
private Event constructEvent(String topic, Object data, boolean async) {
topic = rapifyTopic(instanceId, topic);
Event event;
if (data instanceof Dictionary<?,?>) {
Dictionary<String,Object> properties = (Dictionary<String,Object>)data;
if (async)
properties.put(ASYNC_EVENT, Boolean.TRUE);
event = new Event(topic, properties);
} else if (data instanceof Map<?,?>) {
Map<String,Object> properties = (Map<String,Object>)data;
if (async)
properties.put(ASYNC_EVENT, Boolean.TRUE);
event = new Event(topic, properties);
} else {
Dictionary<String, Object> d = new Hashtable<String, Object>(3);
d.put(EventConstants.EVENT_TOPIC, topic);
if (data != null)
d.put(IEventBroker.DATA, data);
if (async)
d.put(ASYNC_EVENT, Boolean.TRUE);
event = new Event(topic, d);
}
return event;
}
public boolean subscribe(String topic, EventHandler eventHandler) {
return subscribe(topic, null, eventHandler, false);
}
public boolean subscribe(String topic, String filter, EventHandler eventHandler, boolean headless) {
topic = rapifyTopic(instanceId, topic);
BundleContext bundleContext = Activator.getDefault().getBundleContext();
if (bundleContext == null) {
logger.error(NLS.bind("No EventAdmin", topic));
return false;
}
String[] topics = new String[] {topic};
Dictionary<String, Object> d = new Hashtable<String, Object>();
d.put(EventConstants.EVENT_TOPIC, topics);
if (filter != null)
d.put(EventConstants.EVENT_FILTER, filter);
EventHandler wrappedHandler = new RAPUIEventHandler(eventHandler, headless ? null : uiSync);
ServiceRegistration<?> registration = bundleContext.registerService(
EventHandler.class.getName(), wrappedHandler, d);
Collection<ServiceRegistration<?>> handled = registrations
.get(eventHandler);
if (handled == null) {
registrations.put(eventHandler,
handled = new ArrayList<ServiceRegistration<?>>());
}
handled.add(registration);
return true;
}
public boolean unsubscribe(EventHandler eventHandler) {
Collection<ServiceRegistration<?>> handled = registrations
.remove(eventHandler);
if (handled == null || handled.isEmpty())
return false;
for (ServiceRegistration<?> r : handled) {
r.unregister();
}
return true;
}
@PreDestroy
void dispose() {
Collection<Collection<ServiceRegistration<?>>> values = new ArrayList<Collection<ServiceRegistration<?>>>(
registrations.values());
registrations.clear();
for (Collection<ServiceRegistration<?>> handled : values) {
for (ServiceRegistration<?> registration : handled) {
// System.out.println("EventBroker dispose:" + registration[i] +
// ")");
registration.unregister();
}
}
}
public static String rapifyTopic(String instanceId, String topic) {
String rv = instanceId + "/" + topic;
// System.err.println("Original: " + topic + ", RAPified: " + rv);
return rv;
}
public static boolean isAsyncEvent(Event event) {
return Boolean.TRUE.equals(event.getProperty(ASYNC_EVENT));
}
}