blob: 3ef0fd57361e318048a548b6676bacacef764c86 [file] [log] [blame]
/*******************************************************************************
* 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.equinox.internal.event;
import java.security.Permission;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.service.event.*;
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,NLS.bind(EventAdminMsg.EVENT_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, NLS.bind(EventAdminMsg.EVENT_DISPATCH_HANDLER_EXCEPTION, event, handlerService), t);
}
}
}