Package org.knopflerfish.bundle.event

Source Code of org.knopflerfish.bundle.event.MultiListener

/*
* Copyright (c) 2005-2010, KNOPFLERFISH project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
*   notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above
*   copyright notice, this list of conditions and the following
*   disclaimer in the documentation and/or other materials
*   provided with the distribution.
*
* - Neither the name of the KNOPFLERFISH project nor the names of its
*   contributors may be used to endorse or promote products derived
*   from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package org.knopflerfish.bundle.event;

import org.knopflerfish.service.log.LogRef;
import org.knopflerfish.service.log.LogService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.log.LogEntry;
import org.osgi.service.log.LogListener;
import org.osgi.service.log.LogReaderService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

/**
* Listen for LogEntries, ServiceEvents, FrameworkEvents, BundleEvents
*
* @author Magnus Klack, Martin Berg (refactoring by Bj\u00f6rn Andersson)
*/
public class MultiListener implements LogListener,
                                      ServiceListener,
                                      FrameworkListener,
                                      BundleListener {
  private long ourBundleId;
  ServiceTracker logReaderTracker = new ServiceTracker(Activator.bc,LogReaderService.class.getName(), new ServiceTrackerCustomizer(){

    public Object addingService(ServiceReference sr) {
      LogReaderService logReader = (LogReaderService) Activator.bc.getService(sr);
      if (logReader != null) {
        logReader.addLogListener(MultiListener.this);
      }
      return logReader;
    }

    public void modifiedService(ServiceReference sr, Object o) {
    }

    public void removedService(ServiceReference sr, Object o) {
      ((LogReaderService)o).removeLogListener(MultiListener.this);
    }
  });


  void start() {
    ourBundleId = Activator.bc.getBundle().getBundleId();
    Activator.bc.addBundleListener(this);
    Activator.bc.addServiceListener(this);
    Activator.bc.addFrameworkListener(this);
    logReaderTracker.open();

  }

  void stop() {
    logReaderTracker.close();
    Activator.bc.removeBundleListener(this);
    Activator.bc.removeServiceListener(this);
    Activator.bc.removeFrameworkListener(this);

  }

  private static final String BUNDLE_EVENT_PREFIX = "org/osgi/framework/BundleEvent/";
  private static final String INSTALLED_TOPIC = BUNDLE_EVENT_PREFIX + "INSTALLED";
  private static final String STARTED_TOPIC = BUNDLE_EVENT_PREFIX + "STARTED";
  private static final String STOPPED_TOPIC = BUNDLE_EVENT_PREFIX + "STOPPED";
  private static final String UPDATED_TOPIC = BUNDLE_EVENT_PREFIX + "UPDATED";
  private static final String UNINSTALLED_TOPIC = BUNDLE_EVENT_PREFIX + "UNINSTALLED";
  private static final String RESOLVED_TOPIC = BUNDLE_EVENT_PREFIX + "RESOLVED";
  private static final String UNRESOLVED_TOPIC = BUNDLE_EVENT_PREFIX + "UNRESOLVED";

  /**
   * A listener for events sent by bundles
   * @param bundleEvent The event sent by the bundle
   * @author Johnny Baveras
   */


  public void bundleChanged(BundleEvent bundleEvent) {
    String topic = null;
    boolean knownMessageType = true;

    switch (bundleEvent.getType()) {
    case BundleEvent.INSTALLED:
      topic = INSTALLED_TOPIC;
      break;
    case BundleEvent.STARTED:
      topic = STARTED_TOPIC;
      break;
    case BundleEvent.STOPPED:
      topic = STOPPED_TOPIC;
      break;
    case BundleEvent.UPDATED:
      topic = UPDATED_TOPIC;
      break;
    case BundleEvent.UNINSTALLED:
      topic = UNINSTALLED_TOPIC;
      break;
    case BundleEvent.RESOLVED:
      topic = RESOLVED_TOPIC;
      break;
    case BundleEvent.UNRESOLVED:
      topic = UNRESOLVED_TOPIC;
      break;
    default:
      /* Setting the boolean to false if an unknown event arrives */
      knownMessageType = false;
      break;
    }


    /* Stores the properties of the event in the dictionary, if the event is known */
    if (knownMessageType) {
      if(!Activator.handlerTracker.anyHandlersMatching(topic)) {
        return;
      }
      Dictionary props = new Hashtable();
      Bundle bundle = bundleEvent.getBundle();
      putProp(props, EventConstants.EVENT, bundleEvent);
      putProp(props, "bundle.id", new Long(bundle.getBundleId()));
      putProp(props, EventConstants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
      putProp(props, "bundle", bundle);
      /* Tries posting the event once the properties are set */
      try {
        Activator.eventAdmin.postEvent(new Event(topic, props));
      } catch (Exception e) {
        Activator.log.error("EXCEPTION in bundleChanged()", e);
      }
    } else {
      /* Logs an error if the event, which arrived, were of an unknown type */
      Activator.log.error("Recieved unknown bundle event message (type="
                +bundleEvent.getType() +"), discarding");
    }
    // }
  }

  private static final String LOG_PREFIX = "org/osgi/service/log/LogEntry/";
  private static final String LOG_ERROR_TOPIC = LOG_PREFIX + "LOG_ERROR";
  private static final String LOG_WARNING_TOPIC = LOG_PREFIX + "LOG_WARNING";
  private static final String LOG_INFO_TOPIC = LOG_PREFIX + "LOG_INFO";
  private static final String LOG_DEBUG_TOPIC = LOG_PREFIX + "LOG_DEBUG";
  private static final String LOG_OTHER_TOPIC = LOG_PREFIX + "LOG_OTHER";

  /**
   * A listener for entries in the log
   * @param logEntry the entry of the log
   * @author Johnny Baveras
   */
  private Hashtable thrownByPostEvent = new Hashtable();
  public void logged(LogEntry logEntry) {
    // In order to prevent endless loops we ignore errors logged by this method
    if(logEntry.getBundle().getBundleId() ==  ourBundleId &&
       logEntry.getLevel() == LogService.LOG_ERROR &&
       thrownByPostEvent.contains(logEntry.getException())) {

      thrownByPostEvent.remove(logEntry.getException());
      return;
    }
    // If postEvent has thrown and we have logged those errors
    // but haven't been called back within a timeout we stop
    // tracking the throwables
    final long timeout = 60 * 1000;
    if(!thrownByPostEvent.isEmpty()) {
      Iterator entries = thrownByPostEvent.entrySet().iterator();
      while(entries.hasNext()) {
        Map.Entry timestampedThrowable = (Map.Entry)entries.next();
        long timestamp = ((Long)timestampedThrowable.getValue()).longValue();
        if(System.currentTimeMillis() > (timestamp + timeout)) {
          entries.remove();
        }
      }
    }

    String topic = null;

    switch (logEntry.getLevel()) {
    case LogRef.LOG_ERROR:
      topic = LOG_ERROR_TOPIC;
      break;
    case LogRef.LOG_WARNING:
      topic = LOG_WARNING_TOPIC;
      break;
    case LogRef.LOG_INFO:
      topic = LOG_INFO_TOPIC;
      break;
    case LogRef.LOG_DEBUG:
      topic = LOG_DEBUG_TOPIC;
      break;
    default:
      /* if an unknown event arrives, it should be logged as a LOG_OTHER event */
      topic = LOG_OTHER_TOPIC;
      break;
    }

    if(!Activator.handlerTracker.anyHandlersMatching(topic)) {
      return;
    }


    Bundle bundle = logEntry.getBundle();
    Dictionary props = new Hashtable();

    /* Stores the properties of the event in the dictionary */
    if (bundle != null) {
      putProp(props, "bundle.id", new Long(bundle.getBundleId()));
      putProp(props, EventConstants.BUNDLE_SYMBOLICNAME, bundle.getLocation());
      putProp(props, "bundle", bundle);
    }
    if (logEntry != null) {
      putProp(props, "log.level", new Integer(logEntry.getLevel()));
      putProp(props, EventConstants.MESSAGE, logEntry.getMessage());
      putProp(props, EventConstants.TIMESTAMP, new Long(logEntry.getTime()));
      putProp(props, "log.entry", logEntry);
    }

    /* If the event contains an exception, further properties shall be set */
    if (logEntry.getException() != null) {
      Throwable e = logEntry.getException();
      putProp(props, EventConstants.EXECPTION_CLASS, e.getClass().getName());
      putProp(props, EventConstants.EXCEPTION_MESSAGE, e.getMessage());
      putProp(props, EventConstants.EXCEPTION, e);
    }

    /* If the event contains a service reference, further properties shall be set */
    if (logEntry.getServiceReference() != null) {
      putProp(props, EventConstants.SERVICE, logEntry.getServiceReference());
      putProp(props, EventConstants.SERVICE_ID, logEntry.getServiceReference().getProperty(Constants.SERVICE_ID));
      putProp(props, EventConstants.SERVICE_OBJECTCLASS, logEntry.getServiceReference().getProperty(Constants.OBJECTCLASS));
      putProp(props, EventConstants.SERVICE_PID, logEntry.getServiceReference().getProperty(Constants.SERVICE_PID));
    }

    /* Tries posting the event once the properties are set */
    try {
      Activator.eventAdmin.postEvent(new Event(topic, props));
    } catch (Throwable t) {
      // We don't log more errors if postEvent has thrown more than
      // 5 times and we haven't gotten called back for those entries
      // within a certain time
      // See beginning of this method
      if(thrownByPostEvent.size() < 5) {
        thrownByPostEvent.put(t, new Long(System.currentTimeMillis()));
        if(Activator.log.doError()) {
          Activator.log.error("EXCEPTION in logged(LogEntry logEntry):", t);
        }
      }
    }
  }

  private static final String SERVICE_EVENT_PREFIX = "org/osgi/framework/ServiceEvent/";
  private static final String SERVICE_EVENT_REGISTERED_TOPIC = SERVICE_EVENT_PREFIX + "REGISTERED";
  private static final String SERVICE_EVENT_MODIFIED_TOPIC = SERVICE_EVENT_PREFIX + "MODIFIED";
  private static final String SERVICE_EVENT_UNREGISTERING_TOPIC = SERVICE_EVENT_PREFIX + "UNREGISTERING";

  /**
   * A listener for service events
   * @param serviceEvent the event sent by the service
   * @author Johnny Baveras
   */
  public void serviceChanged(ServiceEvent serviceEvent) {
    String topic = null;
    boolean knownMessageType = true;

    switch (serviceEvent.getType()) {
    case ServiceEvent.REGISTERED:
      topic = SERVICE_EVENT_REGISTERED_TOPIC;

     
      String[] objectClass = (String[]) serviceEvent.getServiceReference().getProperty(Constants.OBJECTCLASS);
      boolean isLogReaderService = false;
      if (objectClass != null) {
        for (int i=0; i<objectClass.length; i++) {
          if (LogReaderService.class.getName().equals(objectClass[i])) {
            isLogReaderService = true;
          }
        }
      }

      if (isLogReaderService) {
        LogReaderService logReader = (LogReaderService)
          Activator.bc.getService(serviceEvent.getServiceReference());
        if (logReader != null) {
          logReader.addLogListener(this);
        }
      }
      break;
    case ServiceEvent.MODIFIED:
      topic = SERVICE_EVENT_MODIFIED_TOPIC;
      break;
    case ServiceEvent.UNREGISTERING:
      topic = SERVICE_EVENT_UNREGISTERING_TOPIC;
      break;
    default:
      /* Setting the boolean to false if an unknown event arrives */
      knownMessageType = false;
      break;
    }



    /* Stores the properties of the event in the dictionary, if the event is known */
    if (knownMessageType) {
      if(!Activator.handlerTracker.anyHandlersMatching(topic)) {
        return;
      }
      Dictionary props = new Hashtable();
      putProp(props, EventConstants.EVENT, serviceEvent);
      putProp(props, EventConstants.SERVICE, serviceEvent.getServiceReference());
      putProp(props, EventConstants.SERVICE_PID, serviceEvent.getServiceReference().getProperty(Constants.SERVICE_PID));
      putProp(props, EventConstants.SERVICE_ID, serviceEvent.getServiceReference().getProperty(Constants.SERVICE_ID));
      putProp(props, EventConstants.SERVICE_OBJECTCLASS, serviceEvent.getServiceReference().getProperty(Constants.OBJECTCLASS));

      /* Tries posting the event once the properties are set */
      try {
        Activator.eventAdmin.postEvent(new Event(topic, props));
      } catch (Exception e) {
        Activator.log.error("EXCEPTION in serviceChanged() :", e);
      }
    } else {
      /* Logs an error if the event, which arrived, were of an unknown type */
      Activator.log.error("Recieved unknown service event message (type="
                +serviceEvent.getType() +"), discarding");
    }
  }

  private static final String FW_EVT_PREFIX = "org/osgi/framework/FrameworkEvent/";
  private static final String FW_EVT_STARTED = FW_EVT_PREFIX + "STARTED";
  private static final String FW_EVT_ERROR = FW_EVT_PREFIX + "ERROR";
  private static final String FW_EVT_INFO = FW_EVT_PREFIX + "INFO";
  private static final String FW_EVT_PACKAGES_REFRESHED = FW_EVT_PREFIX + "PACKAGES_REFRESHED";
  private static final String FW_EVT_STARTLEVEL_CHANGED = FW_EVT_PREFIX + "STARTLEVEL_CHANGED";
  /**
   * A listener of framework events
   * @param frameworkEvent the event sent by the framework
   * @author Johnny Baveras
   */
  public void frameworkEvent(FrameworkEvent frameworkEvent) {
    String topic = null;
    boolean knownMessageType = true;
   
    switch (frameworkEvent.getType()) {
    case FrameworkEvent.STARTED:
      topic = FW_EVT_STARTED;
      break;
    case FrameworkEvent.ERROR:
      topic = FW_EVT_ERROR;
      break;
    case FrameworkEvent.INFO:
      topic = FW_EVT_INFO;
      break;
    case FrameworkEvent.PACKAGES_REFRESHED:
      topic = FW_EVT_PACKAGES_REFRESHED;
      break;
    case FrameworkEvent.STARTLEVEL_CHANGED:
      topic = FW_EVT_STARTLEVEL_CHANGED;
      break;
    default:
      /* Setting the boolean to false if an unknown event arrives */
      knownMessageType = false;
      break;
    }

    if (knownMessageType) {
      if(!Activator.handlerTracker.anyHandlersMatching(topic)) {
        return;
      }
      Dictionary props = new Hashtable();
      Bundle bundle = frameworkEvent.getBundle();
      putProp(props, "event", frameworkEvent);
      /* If the event contains a bundle, further properties shall be set */
      if (frameworkEvent.getBundle() != null) {
        putProp(props, "bundle.id", new Long(bundle.getBundleId()));
        putProp(props,
                EventConstants.BUNDLE_SYMBOLICNAME,
                bundle.getLocation());
        putProp(props, "bundle", bundle);
      }

      /* If the event contains an exception, further properties shall be set */
      if (frameworkEvent.getThrowable() != null) {
        Throwable e = frameworkEvent.getThrowable();
        putProp(props,
                EventConstants.EXECPTION_CLASS,
                Throwable.class.getName());
        putProp(props, EventConstants.EXCEPTION_MESSAGE, e.getMessage());
        putProp(props, EventConstants.EXCEPTION, e);
      }

      /* Tries posting the event once the properties are set */
      try {
        Activator.eventAdmin.postEvent(new Event(topic, props));
      } catch (Exception e) {
        Activator.log.error("Exception in frameworkEvent() :", e);
      }
    } else {
      Activator.log.error("Recieved unknown framework event (type="
                +frameworkEvent.getType() +"), discarding");
    }
  }

  private void putProp(Dictionary props, Object key, Object value) {
    if (value != null) {
      props.put(key, value);
    }
  }
}
TOP

Related Classes of org.knopflerfish.bundle.event.MultiListener

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.