public void fireBundleEvent(BundleEvent event)
    {
        // Take a snapshot of the listener array.
        Map<BundleContext, List<ListenerInfo>> listeners = null;
        Map<BundleContext, List<ListenerInfo>> syncListeners = null;
        synchronized (this)
        {
            listeners = m_bndlListeners;
            syncListeners = m_syncBndlListeners;
        }

        // Create a whitelist of bundle context for bundle listeners,
        // if we have hooks.
        Set<BundleContext> whitelist = createWhitelistFromHooks(event, event.getBundle(),
            listeners, syncListeners, org.osgi.framework.hooks.bundle.EventHook.class);

        // If we have a whitelist, then create copies of only the whitelisted
        // listeners.
        if (whitelist != null)
        {
            Map<BundleContext, List<ListenerInfo>> copy =
                new HashMap<BundleContext, List<ListenerInfo>>();
            for (BundleContext bc : whitelist)
            {
                List<ListenerInfo> infos = listeners.get(bc);
                if (infos != null)
                {
                    copy.put(bc, infos);
                }
            }
            listeners = copy;
            copy = new HashMap<BundleContext, List<ListenerInfo>>();
            for (BundleContext bc : whitelist)
            {
                List<ListenerInfo> infos = syncListeners.get(bc);
                if (infos != null)
                {
                    copy.put(bc, infos);
                }
            }
            syncListeners = copy;
        }

        // Fire synchronous bundle listeners immediately on the calling thread.
        fireEventImmediately(
            this, Request.BUNDLE_EVENT, syncListeners, event, null);

        // The spec says that asynchronous bundle listeners do not get events
        // of types STARTING, STOPPING, or LAZY_ACTIVATION.
        if ((event.getType() != BundleEvent.STARTING)
            && (event.getType() != BundleEvent.STOPPING)
            && (event.getType() != BundleEvent.LAZY_ACTIVATION))
        {
            // Fire asynchronous bundle listeners on a separate thread.
            fireEventAsynchronously(
                this, Request.BUNDLE_EVENT, listeners, event);
        }
    }