| /******************************************************************************* |
| * Copyright (c) 2007, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.ecf.internal.remoteservice.eventadmin; |
| |
| import java.security.Permission; |
| |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.Filter; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.event.Event; |
| import org.osgi.service.event.EventConstants; |
| import org.osgi.service.event.EventHandler; |
| import org.osgi.service.log.LogService; |
| |
| /** |
| * A wrapper for EventHandlers. This class caches property values and performs |
| * final checks before calling the wrapped handler. |
| * |
| */ |
| public class EventHandlerWrapper { |
| private final ServiceReference reference; |
| private final LogService log; |
| private final BundleContext context; |
| private EventHandler handler; |
| private String[] topics; |
| private Filter filter; |
| |
| /** |
| * Create an EventHandlerWrapper. |
| * |
| * @param reference |
| * Reference to the EventHandler |
| * @param context |
| * Bundle Context of the Event Admin bundle |
| * @param log |
| * LogService object for logging |
| */ |
| public EventHandlerWrapper(ServiceReference reference, |
| BundleContext context, LogService log) { |
| this.reference = reference; |
| this.context = context; |
| this.log = log; |
| } |
| |
| /** |
| * Cache values from service properties |
| * |
| * @return true if the handler should be called; false if the handler should |
| * not be called |
| */ |
| public synchronized boolean init() { |
| topics = null; |
| filter = null; |
| |
| // Get topic names |
| Object o = reference.getProperty(EventConstants.EVENT_TOPIC); |
| if (o instanceof String) { |
| topics = new String[] { (String) o }; |
| } else if (o instanceof String[]) { |
| topics = (String[]) o; |
| } |
| |
| if (topics == null) { |
| return false; |
| } |
| |
| // get filter |
| o = reference.getProperty(EventConstants.EVENT_FILTER); |
| if (o instanceof String) { |
| try { |
| filter = context.createFilter((String) o); |
| } catch (InvalidSyntaxException e) { |
| log.log(LogService.LOG_ERROR, "Invalid handler filter "+o, e); |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Flush the handler service if it has been obtained. |
| */ |
| public void flush() { |
| synchronized (this) { |
| if (handler == null) { |
| return; |
| } |
| handler = null; |
| } |
| context.ungetService(reference); |
| } |
| |
| /** |
| * Get the event topics for the wrapped handler. |
| * |
| * @return The wrapped handler's event topics |
| */ |
| public synchronized String[] getTopics() { |
| return topics; |
| } |
| |
| /** |
| * Return the wrapped handler. |
| * |
| * @return The wrapped handler. |
| */ |
| private EventHandler getHandler() { |
| synchronized (this) { |
| // if we already have a handler, return it |
| if (handler != null) { |
| return handler; |
| } |
| } |
| |
| // we don't have the handler, so lets get it outside the sync region |
| EventHandler tempHandler = (EventHandler) context.getService(reference); |
| |
| synchronized (this) { |
| // do we still need the handler we just got? |
| if (handler == null) { |
| handler = tempHandler; |
| return handler; |
| } |
| // get the current handler |
| tempHandler = handler; |
| } |
| |
| // unget the handler we just got since we don't need it |
| context.ungetService(reference); |
| |
| // return the current handler (copied into the local var) |
| return tempHandler; |
| } |
| |
| /** |
| * Get the filter object |
| * |
| * @return The handler's filter |
| */ |
| private synchronized Filter getFilter() { |
| return filter; |
| } |
| |
| /** |
| * Dispatch event to handler. Perform final tests before actually calling |
| * the handler. |
| * |
| * @param event |
| * The event to dispatch |
| * @param perm |
| * The permission to be checked |
| */ |
| public void handleEvent(Event event, Permission perm) { |
| Bundle bundle = reference.getBundle(); |
| // is service unregistered? |
| if (bundle == null) { |
| return; |
| } |
| |
| // filter match |
| Filter eventFilter = getFilter(); |
| if ((eventFilter != null) && !event.matches(eventFilter)) { |
| return; |
| } |
| |
| // permission check |
| if ((perm != null) && (!bundle.hasPermission(perm))) { |
| return; |
| } |
| |
| // get handler service |
| EventHandler handlerService = getHandler(); |
| if (handlerService == null) { |
| return; |
| } |
| |
| try { |
| handlerService.handleEvent(event); |
| } catch (Throwable t) { |
| // log/handle any Throwable thrown by the listener |
| log.log(LogService.LOG_ERROR, "Exception while dispatching event "+event+" to handler "+handlerService, t); |
| } |
| } |
| } |