Package org.eclipse.ecf.internal.remoteservice.eventadmin

Source Code of org.eclipse.ecf.internal.remoteservice.eventadmin.EventHandlerWrapper

/*******************************************************************************
* 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);
    }
  }
}
TOP

Related Classes of org.eclipse.ecf.internal.remoteservice.eventadmin.EventHandlerWrapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.