private static void dispatchServiceRegistrationEvents(
      ServiceReference[] alreadyRegistered, ServiceListener listener) {
    if (log.isTraceEnabled())
      log.trace(
          "Calling listener for already registered services: "
              + ObjectUtils.nullSafeToString(alreadyRegistered));

    if (alreadyRegistered != null) {
      for (int i = 0; i < alreadyRegistered.length; i++) {
        listener.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, alreadyRegistered[i]));
      }
    }
  }
  /**
   * Bottom level event dispatcher for the BundleContext.
   *
   * @param originalListener listener object registered under.
   * @param l listener to call (may be filtered).
   * @param action Event class type
   * @param object Event object
   */
  public void dispatchEvent(Object originalListener, Object l, int action, Object object) {
    // save the bundle ref to a local variable
    // to avoid interference from another thread closing this context
    AbstractBundle tmpBundle = bundle;
    Object previousTCCL = setContextFinder();
    try {
      if (isValid()) /* if context still valid */ {
        switch (action) {
          case Framework.BUNDLEEVENT:
          case Framework.BUNDLEEVENTSYNC:
            {
              BundleListener listener = (BundleListener) l;

              if (Debug.DEBUG_EVENTS) {
                String listenerName =
                    listener.getClass().getName()
                        + "@"
                        + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$
                Debug.println(
                    "dispatchBundleEvent["
                        + tmpBundle
                        + "]("
                        + listenerName
                        + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
              }

              BundleEvent event = (BundleEvent) object;
              switch (event.getType()) {
                case Framework.BATCHEVENT_BEGIN:
                  {
                    if (listener instanceof BatchBundleListener)
                      ((BatchBundleListener) listener).batchBegin();
                    break;
                  }
                case Framework.BATCHEVENT_END:
                  {
                    if (listener instanceof BatchBundleListener)
                      ((BatchBundleListener) listener).batchEnd();
                    break;
                  }
                default:
                  {
                    listener.bundleChanged((BundleEvent) object);
                  }
              }
              break;
            }

          case ServiceRegistry.SERVICEEVENT:
            {
              ServiceEvent event = (ServiceEvent) object;

              ServiceListener listener = (ServiceListener) l;
              if (Debug.DEBUG_EVENTS) {
                String listenerName =
                    listener.getClass().getName()
                        + "@"
                        + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$
                Debug.println(
                    "dispatchServiceEvent["
                        + tmpBundle
                        + "]("
                        + listenerName
                        + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
              }
              listener.serviceChanged(event);

              break;
            }

          case Framework.FRAMEWORKEVENT:
            {
              FrameworkListener listener = (FrameworkListener) l;

              if (Debug.DEBUG_EVENTS) {
                String listenerName =
                    listener.getClass().getName()
                        + "@"
                        + Integer.toHexString(System.identityHashCode(listener)); // $NON-NLS-1$
                Debug.println(
                    "dispatchFrameworkEvent["
                        + tmpBundle
                        + "]("
                        + listenerName
                        + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
              }

              listener.frameworkEvent((FrameworkEvent) object);
              break;
            }
          default:
            {
              throw new InternalError();
            }
        }
      }
    } catch (Throwable t) {
      if (Debug.DEBUG_GENERAL) {
        Debug.println(
            "Exception in bottom level event dispatcher: " + t.getMessage()); // $NON-NLS-1$
        Debug.printStackTrace(t);
      }
      // allow the adaptor to handle this unexpected error
      framework.adaptor.handleRuntimeError(t);
      publisherror:
      {
        if (action == Framework.FRAMEWORKEVENT) {
          FrameworkEvent event = (FrameworkEvent) object;
          if (event.getType() == FrameworkEvent.ERROR) {
            break publisherror; // avoid infinite loop
          }
        }

        framework.publishFrameworkEvent(FrameworkEvent.ERROR, tmpBundle, t);
      }
    } finally {
      if (previousTCCL != Boolean.FALSE)
        Thread.currentThread().setContextClassLoader((ClassLoader) previousTCCL);
    }
  }