001/*******************************************************************************
002 * Copyright (c) 2009, 2013 IBM Corporation and others.
003 * All rights reserved. This program and the accompanying materials
004 * are made available under the terms of the Eclipse Public License v1.0
005 * which accompanies this distribution, and is available at
006 * http://www.eclipse.org/legal/epl-v10.html
007 * 
008 * Contributors:
009 *     IBM Corporation - initial API and implementation
010 *     Florian Pirchner - adjustments to osbp code
011 *******************************************************************************/
012package org.eclipse.osbp.runtime.event;
013
014import java.util.ArrayList;
015import java.util.Collection;
016import java.util.Dictionary;
017import java.util.HashMap;
018import java.util.Hashtable;
019import java.util.Map;
020
021import org.eclipse.osbp.runtime.common.event.IEventBroker;
022import org.osgi.framework.BundleContext;
023import org.osgi.framework.ServiceRegistration;
024import org.osgi.service.component.ComponentContext;
025import org.osgi.service.component.annotations.Activate;
026import org.osgi.service.component.annotations.Component;
027import org.osgi.service.component.annotations.Deactivate;
028import org.osgi.service.component.annotations.Reference;
029import org.osgi.service.component.annotations.ReferenceCardinality;
030import org.osgi.service.event.Event;
031import org.osgi.service.event.EventAdmin;
032import org.osgi.service.event.EventConstants;
033import org.osgi.service.event.EventHandler;
034
035@Component
036public class EventBroker implements IEventBroker {
037
038    // private static final Logger LOGGER = LoggerFactory
039    // .getLogger(EventBroker.class);
040
041    // TBD synchronization
042    private Map<EventHandler, Collection<ServiceRegistration<?>>> registrations = new HashMap<EventHandler, Collection<ServiceRegistration<?>>>();
043
044    private EventAdmin eventAdmin;
045
046    private ComponentContext context;
047
048    public EventBroker() {
049        // placeholder
050    }
051
052    @Activate
053    protected void activate(ComponentContext context) {
054        this.context = context;
055    }
056
057    @Deactivate
058    protected void deactivate(ComponentContext context) {
059        Collection<Collection<ServiceRegistration<?>>> values = new ArrayList<Collection<ServiceRegistration<?>>>(
060                registrations.values());
061        registrations.clear();
062        for (Collection<ServiceRegistration<?>> handled : values) {
063            for (ServiceRegistration<?> registration : handled) {
064                registration.unregister();
065            }
066        }
067
068        this.context = null;
069    }
070
071    @Reference(cardinality = ReferenceCardinality.MANDATORY, unbind = "unbindEventAdmin")
072    protected void bindEventAdmin(EventAdmin eventAdmin) {
073        this.eventAdmin = eventAdmin;
074    }
075
076    protected void unbindEventAdmin(EventAdmin eventAdmin) {
077        this.eventAdmin = null;
078    }
079
080    @Override
081    public boolean send(String topic, Object data) {
082        Event event = constructEvent(topic, data);
083        eventAdmin.sendEvent(event);
084        return true;
085    }
086
087    @Override
088    public boolean post(String topic, Object data) {
089        Event event = constructEvent(topic, data);
090        eventAdmin.postEvent(event);
091        return true;
092    }
093
094    @SuppressWarnings("unchecked")
095    private Event constructEvent(String topic, Object data) {
096        Event event;
097        if (data instanceof Dictionary<?, ?>) {
098            event = new Event(topic, (Dictionary<String, ?>) data);
099        } else if (data instanceof Map<?, ?>) {
100            event = new Event(topic, (Map<String, ?>) data);
101        } else {
102            Dictionary<String, Object> d = new Hashtable<String, Object>(2);
103            d.put(EventConstants.EVENT_TOPIC, topic);
104            if (data != null)
105                d.put(IEventBroker.DATA, data);
106            event = new Event(topic, d);
107        }
108        return event;
109    }
110
111    @Override
112    public boolean subscribe(String topic, EventHandler eventHandler) {
113        return subscribe(topic, null, eventHandler, false);
114    }
115
116    @Override
117    public boolean subscribe(String topic, String filter,
118            EventHandler eventHandler, boolean headless) {
119        BundleContext bundleContext = context.getBundleContext();
120        String[] topics = new String[] { topic };
121        Dictionary<String, Object> d = new Hashtable<String, Object>();
122        d.put(EventConstants.EVENT_TOPIC, topics);
123        if (filter != null) {
124            d.put(EventConstants.EVENT_FILTER, filter);
125        }
126        ServiceRegistration<?> registration = bundleContext.registerService(
127                EventHandler.class.getName(), eventHandler, d);
128        Collection<ServiceRegistration<?>> handled = registrations
129                .get(eventHandler);
130        if (handled == null) {
131            registrations.put(eventHandler,
132                    handled = new ArrayList<ServiceRegistration<?>>());
133        }
134        handled.add(registration);
135        return true;
136    }
137
138    @Override
139    public boolean unsubscribe(EventHandler eventHandler) {
140        Collection<ServiceRegistration<?>> handled = registrations
141                .remove(eventHandler);
142        if (handled == null || handled.isEmpty())
143            return false;
144        for (ServiceRegistration<?> r : handled) {
145            r.unregister();
146        }
147        return true;
148    }
149}