Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * #%L
   * JBossOSGi Framework
   * %%
   * Copyright (C) 2010 - 2012 JBoss by Red Hat
   * %%
   * This program is free software: you can redistribute it and/or modify
   * it under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation, either version 2.1 of the
  * License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Lesser Public License for more details.
  *
  * You should have received a copy of the GNU General Lesser Public
  * License along with this program.  If not, see
  * <http://www.gnu.org/licenses/lgpl-2.1.html>.
  * #L%
  */
 package org.jboss.osgi.framework.internal;
 
 import static org.jboss.osgi.framework.FrameworkLogger.LOGGER;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 
 final class FrameworkEventsImpl implements FrameworkEvents {
 
     private final BundleManagerPlugin bundleManager;
     private final ExecutorService executorService;
     private final LockManager lockManager;

    
The bundleState listeners
 
     private final Map<XBundleList<BundleListener>> bundleListeners = new ConcurrentHashMap<XBundleList<BundleListener>>();
    
The framework listeners
 
The service listeners
 
The set of bundleState events that are delivered to an (asynchronous) BundleListener
 
     private Set<IntegerasyncBundleEvents = new HashSet<Integer>();
    
The set of events that are logged at INFO level
 
     private Set<StringinfoEvents = new HashSet<String>();
 
     FrameworkEventsImpl(BundleManager bundleManagerExecutorService executorServiceLockManager lockManager) {
         this. = BundleManagerPlugin.assertBundleManagerPlugin(bundleManager);
         this. = executorService;
         this. = lockManager;
        .add(ConstantsHelper.frameworkEvent(.));
        .add(ConstantsHelper.frameworkEvent(.));
        .add(ConstantsHelper.frameworkEvent(.));
        .add(ConstantsHelper.bundleEvent(.));
        .add(ConstantsHelper.bundleEvent(.));
        .add(ConstantsHelper.bundleEvent(.));
        .add(ConstantsHelper.bundleEvent(.));
    }
    @Override
    public void addBundleListener(final XBundle bundlefinal BundleListener listener) {
        assert listener != null : "Null listener";
        synchronized () {
            List<BundleListenerlisteners = .get(bundle);
            if (listeners == null) {
                listeners = new CopyOnWriteArrayList<BundleListener>();
                .put(bundlelisteners);
            }
            if (listeners.contains(listener) == false)
                listeners.add(listener);
        }
    }
    @Override
    public void removeBundleListener(final XBundle bundleStatefinal BundleListener listener) {
        assert listener != null : "Null listener";
        synchronized () {
            List<BundleListenerlisteners = .get(bundleState);
            if (listeners != null) {
                if (listeners.size() > 1)
                    listeners.remove(listener);
                else
                    removeBundleListeners(bundleState);
            }
        }
    }
    @Override
    public void removeBundleListeners(final XBundle bundleState) {
        synchronized () {
            .remove(bundleState);
        }
    }
    @Override
    public void removeAllBundleListeners() {
        synchronized () {
            .clear();
        }
    }
    @Override
    public void addFrameworkListener(final XBundle bundleStatefinal FrameworkListener listener) {
        assert listener != null : "Null listener";
        synchronized () {
            List<FrameworkListenerlisteners = .get(bundleState);
            if (listeners == null) {
                listeners = new CopyOnWriteArrayList<FrameworkListener>();
                .put(bundleStatelisteners);
            }
            if (listeners.contains(listener) == false)
                listeners.add(listener);
        }
    }
    @Override
    public void removeFrameworkListener(final XBundle bundleStatefinal FrameworkListener listener) {
        assert listener != null : "Null listener";
        synchronized () {
            List<FrameworkListenerlisteners = .get(bundleState);
            if (listeners != null) {
                if (listeners.size() > 1)
                    listeners.remove(listener);
                else
                    removeFrameworkListeners(bundleState);
            }
        }
    }
    @Override
    public void removeFrameworkListeners(final XBundle bundleState) {
        synchronized () {
            .remove(bundleState);
        }
    }
    @Override
    public void removeAllFrameworkListeners() {
        synchronized () {
            .clear();
        }
    }
    @Override
    public void addServiceListener(final XBundle bundleStatefinal ServiceListener listenerfinal String filterstrthrows InvalidSyntaxException {
        assert listener != null : "Null listener";
        synchronized () {
            List<ServiceListenerRegistrationlisteners = .get(bundleState);
            if (listeners == null) {
                listeners = new CopyOnWriteArrayList<ServiceListenerRegistration>();
                .put(bundleStatelisteners);
            }
            // If the context bundleState's list of listeners already contains a listener l such that (l==listener),
            // then this method replaces that listener's filter (which may be null) with the specified one (which may be null).
            removeServiceListener(bundleStatelistener);
            // Create the new listener registration
            Filter filter = (filterstr != null ? FrameworkUtil.createFilter(filterstr) : .);
            ServiceListenerRegistration slreg = new ServiceListenerRegistration(bundleStatelistenerfilter);
            // The {@link ListenerHook} added method is called to provide the hook implementation with information on newly
            // added service listeners.
            // This method will be called as service listeners are added while this hook is registered
            for (ListenerHook hook : getServiceListenerHooks()) {
                try {
                    hook.added(Collections.singleton(slreg.getListenerInfo()));
                } catch (RuntimeException ex) {
                    .errorProcessingServiceListenerHook(exhook);
                }
            }
            // Add the listener to the list
            listeners.add(slreg);
        }
    }
    @Override
    public Collection<ListenerInfogetServiceListenerInfos(final XBundle bundleState) {
        Collection<ListenerInfolisteners = new ArrayList<ListenerInfo>();
        for (Entry<XBundleList<ServiceListenerRegistration>> entry : .entrySet()) {
            if (bundleState == null || bundleState.equals(entry.getKey())) {
                for (ServiceListenerRegistration aux : entry.getValue()) {
                    ListenerInfo info = aux.getListenerInfo();
                    listeners.add(info);
                }
            }
        }
        return Collections.unmodifiableCollection(listeners);
    }
    @Override
    public void removeServiceListener(final XBundle bundleStatefinal ServiceListener listener) {
        assert listener != null : "Null listener";
        synchronized () {
            List<ServiceListenerRegistrationlisteners = .get(bundleState);
            if (listeners != null) {
                ServiceListenerRegistration slreg = new ServiceListenerRegistration(bundleStatelistener.);
                int index = listeners.indexOf(slreg);
                if (index >= 0) {
                    slreg = listeners.remove(index);
                    // The {@link ListenerHook} 'removed' method is called to provide the hook implementation with information
                    // on newly removed service listeners.
                    // This method will be called as service listeners are removed while this hook is registered.
                    for (ListenerHook hook : getServiceListenerHooks()) {
                        try {
                            ListenerInfoImpl info = (ListenerInfoImplslreg.getListenerInfo();
                            info.setRemoved(true);
                            hook.removed(Collections.singleton(info));
                        } catch (RuntimeException ex) {
                            .errorProcessingServiceListenerHook(exhook);
                        }
                    }
                }
            }
        }
    }
    @Override
    public void removeServiceListeners(final XBundle bundleState) {
        synchronized () {
            Collection<ListenerInfolistenerInfos = getServiceListenerInfos(bundleState);
            .remove(bundleState);
            // The {@link ListenerHook} 'removed' method is called to provide the hook implementation with information on newly
            // removed service listeners.
            // This method will be called as service listeners are removed while this hook is registered.
            for (ListenerHook hook : getServiceListenerHooks()) {
                try {
                    hook.removed(listenerInfos);
                } catch (RuntimeException ex) {
                    .errorProcessingServiceListenerHook(exhook);
                }
            }
        }
    }
    @Override
    public void removeAllServiceListeners() {
        synchronized () {
            .clear();
        }
    }
        if (.isFrameworkCreated() == false)
            return Collections.emptyList();
        ServiceReference[] srefs = null;
        SystemBundleState sysBundle = .getSystemBundle();
        BundleContext sysContext = sysBundle.getBundleContext();
        try {
            srefs = sysContext.getServiceReferences(ListenerHook.class.getName(), null);
        } catch (InvalidSyntaxException e) {
            // ignore
        }
        if (srefs == null)
            return Collections.emptyList();
        List<ListenerHookhooks = new ArrayList<ListenerHook>();
        for (ServiceReference sref : srefs)
            hooks.add((ListenerHooksysContext.getService(sref));
        return Collections.unmodifiableList(hooks);
    }
    @Override
    public void fireBundleEvent(final XBundle bundleStatefinal int type) {
        // Do nothing it the framework is not active
        if (.isFrameworkCreated() == false)
            return;
        // Get a snapshot of the current listeners
        final List<BundleListenerlisteners = new ArrayList<BundleListener>();
        synchronized () {
            for (Entry<XBundleList<BundleListener>> entry : .entrySet()) {
                for (BundleListener listener : entry.getValue()) {
                    listeners.add(listener);
                }
            }
        }
        // Expose the bundleState wrapper not the state itself
        final BundleEvent event = new BundleEventImpl(typebundleState);
        final String typeName = ConstantsHelper.bundleEvent(event.getType());
        //System.out.println(event);
        // Nobody is interested
        if (listeners.isEmpty())
            return;
        // Sanity check that we are not holding a lock
        LockContext currentLock = .getCurrentLockContext();
        // Synchronous listeners first
        Iterator<BundleListeneriterator = listeners.iterator();
        while(iterator.hasNext()) {
            BundleListener listener = iterator.next();
            try {
                if (listener instanceof SynchronousBundleListener) {
                    if (currentLock != null) {
                        // This has the potential for deadlock!
                        .debugf("Calling out to client code with current lock: %s"currentLock);
                    }
                    iterator.remove();
                    listener.bundleChanged(event);
                }
            } catch (Throwable th) {
                .warnErrorWhileFiringBundleEvent(thtypeNamebundleState);
            }
        }
        if (!listeners.isEmpty()) {
            Runnable runner = new Runnable() {
                public void run() {
                    // BundleListeners are called with a BundleEvent object when a bundleState has been
                    // installed, resolved, started, stopped, updated, unresolved, or uninstalled
                    if (.contains(type)) {
                        for (BundleListener listener : listeners) {
                            try {
                                if (!(listener instanceof SynchronousBundleListener)) {
                                    listener.bundleChanged(event);
                                }
                            } catch (Throwable th) {
                                .warnErrorWhileFiringBundleEvent(thtypeNamebundleState);
                            }
                        }
                    }
                }
            };
            if (!.isShutdown()) {
                .execute(runner);
            }
        }
    }
    @Override
    public void fireFrameworkEvent(final Bundle bundlefinal int typefinal Throwable th) {
        // Do nothing it the framework is not active
        if (.isFrameworkCreated() == false)
            return;
        // Get a snapshot of the current listeners
        final ArrayList<FrameworkListenerlisteners = new ArrayList<FrameworkListener>();
        synchronized () {
            for (Entry<XBundleList<FrameworkListener>> entry : .entrySet()) {
                for (FrameworkListener listener : entry.getValue()) {
                    listeners.add(listener);
                }
            }
        }
        final FrameworkEvent event = new FrameworkEventImpl(typebundleth);
        final String typeName = ConstantsHelper.frameworkEvent(event.getType());
        switch (event.getType()) {
            case .:
                .errorFrameworkEvent(th);
                break;
            case .:
                .warnFrameworkEvent(th);
                break;
            default:
                .debugf(th"Framework event: %s"typeName);
        }
        // Nobody is interested
        if (listeners.isEmpty())
            return;
        Runnable runner = new Runnable() {
            public void run() {
                // Call the listeners
                for (FrameworkListener listener : listeners) {
                    try {
                        listener.frameworkEvent(event);
                    } catch (RuntimeException ex) {
                        .warnErrorWhileFiringEvent(extypeName);
                        // The Framework must publish a FrameworkEvent.ERROR if a callback to an
                        // event listener generates an unchecked exception - except when the callback
                        // happens while delivering a FrameworkEvent.ERROR
                        if (type != .) {
                            fireFrameworkEvent(bundle.ex);
                        }
                    } catch (Throwable th) {
                        .warnErrorWhileFiringEvent(thtypeName);
                    }
                }
            }
        };
        if (!.isShutdown()) {
            .execute(runner);
        }
    }
    @Override
    public void fireServiceEvent(final XBundle bundleStateint typefinal ServiceState serviceState) {
        // Do nothing it the framework is not active
        if (.isFrameworkCreated() == false)
            return;
        // Get a snapshot of the current listeners
        List<ServiceListenerRegistrationlistenerRegs = new ArrayList<ServiceListenerRegistration>();
        synchronized () {
            for (Entry<XBundleList<ServiceListenerRegistration>> entry : .entrySet()) {
                for (ServiceListenerRegistration listener : entry.getValue()) {
                    BundleContext context = listener.getBundleContext();
                    if (context != null)
                        listenerRegs.add(listener);
                }
            }
        }
        // Expose the wrapper not the state itself
        ServiceEvent event = new ServiceEventImpl(typeserviceState);
        String typeName = ConstantsHelper.serviceEvent(event.getType());
        .tracef("Service %s: %s"typeNameserviceState);
        // Call the registered event hooks
        SystemBundleState sysBundle = .getSystemBundle();
        BundleContext sysContext = sysBundle.getBundleContext();
        listenerRegs = processEventHooks(sysContextlistenerRegsevent);
        // Nobody is interested
        if (listenerRegs.isEmpty())
            return;
        // Call the listeners. All service events are synchronously delivered
        for (ServiceListenerRegistration listenerReg : listenerRegs) {
            // Service events must only be delivered to event listeners which can validly cast the event
            if (listenerReg.isAllServiceListener() == false) {
                XBundle owner = listenerReg.getBundleState();
                boolean assignableToOwner = true;
                String[] clazzes = (String[]) serviceState.getProperty(.);
                for (String clazz : clazzes) {
                    if (serviceState.isAssignableTo(ownerclazz) == false) {
                        assignableToOwner = false;
                        break;
                    }
                }
                if (assignableToOwner == false)
                    continue;
            }
            try {
                String filterstr = listenerReg.filter.toString();
                if (listenerReg.filter.match(serviceState)) {
                    listenerReg.listener.serviceChanged(event);
                }
                // The MODIFIED_ENDMATCH event is synchronously delivered after the service properties have been modified.
                // This event is only delivered to listeners which were added with a non-null filter where
                // the filter matched the service properties prior to the modification but the filter does
                // not match the modified service properties.
                else if (filterstr != null && . == event.getType()) {
                    if (listenerReg.filter.match(serviceState.getPreviousProperties())) {
                        event = new ServiceEventImpl(.serviceState);
                        listenerReg.listener.serviceChanged(event);
                    }
                }
            } catch (Throwable th) {
                .warnErrorWhileFiringServiceEvent(thtypeNameserviceState);
            }
        }
    }
        // Collect the BundleContexts
        Collection<BundleContextcontexts = new HashSet<BundleContext>();
        for (ServiceListenerRegistration listener : listeners) {
            BundleContext context = listener.getBundleContext();
            if (context != null)
                contexts.add(context);
        }
        contexts = new RemoveOnlyCollection<BundleContext>(contexts);
        // Call the registered event hooks
        List<EventHookeventHooks = getEventHooks(syscontext);
        for (EventHook hook : eventHooks) {
            try {
                hook.event(eventcontexts);
            } catch (Exception ex) {
                .warnErrorWhileCallingEventHook(exhook);
            }
        }
        // Remove the listeners that have been filtered by the EventHooks
        if (contexts.size() != listeners.size()) {
            Iterator<ServiceListenerRegistrationit = listeners.iterator();
            while (it.hasNext()) {
                ServiceListenerRegistration slreg = it.next();
                if (contexts.contains(slreg.getBundleContext()) == false)
                    it.remove();
            }
        }
        return listeners;
    }
    private List<EventHookgetEventHooks(BundleContext syscontext) {
        List<EventHookhooks = new ArrayList<EventHook>();
        ServiceReference[] srefs = null;
        try {
            srefs = syscontext.getServiceReferences(EventHook.class.getName(), null);
        } catch (InvalidSyntaxException e) {
            // ignore
        }
        if (srefs != null) {
            // The calling order of the hooks is defined by the reversed compareTo ordering of their Service
            // Reference objects. That is, the service with the highest ranking number is called first.
            List<ServiceReferencesortedRefs = new ArrayList<ServiceReference>(Arrays.asList(srefs));
            Collections.reverse(sortedRefs);
            for (ServiceReference sref : sortedRefs)
                hooks.add((EventHooksyscontext.getService(sref));
        }
        return hooks;
    }

    
Filter and AccessControl for service events
    static class ServiceListenerRegistration {
        private XBundle bundleState;
        private ServiceListener listener;
        private Filter filter;
        private ListenerInfo info;
        // Any access control context
        ServiceListenerRegistration(final XBundle bundleStatefinal ServiceListener listenerfinal Filter filter) {
            assert bundleState != null : "Null bundleState";
            assert listener != null : "Null listener";
            assert filter != null : "Null filter";
            this. = bundleState;
            this. = listener;
            this. = filter;
            this. = new ListenerInfoImpl(this);
            if (System.getSecurityManager() != null)
                 = AccessController.getContext();
        }
        XBundle getBundleState() {
            return ;
        }
        BundleContext getBundleContext() {
            return .getBundleContext();
        }
        ListenerInfo getListenerInfo() {
            return ;
        }
        boolean isAllServiceListener() {
            return ( instanceof AllServiceListener);
        }
        @Override
        public int hashCode() {
            return .hashCode();
        }
        @Override
        public boolean equals(Object obj) {
            if (obj instanceof ServiceListenerRegistration == false)
                return false;
            // Only the ServiceListener instance determins equality
            ServiceListenerRegistration other = (ServiceListenerRegistrationobj;
            return other.listener.equals();
        }
        @Override
        public String toString() {
            String className = .getClass().getName();
            return "ServiceListener[" +  + "," + className + "," +  + "]";
        }
    }
    static class ListenerInfoImpl implements ListenerInfo {
        private BundleContext context;
        private ServiceListener listener;
        private String filter;
        private boolean removed;
        ListenerInfoImpl(final ServiceListenerRegistration slreg) {
            this. = slreg.bundleState.getBundleContext();
            this. = slreg.listener;
            this. = slreg.filter.toString();
        }
        @Override
        public BundleContext getBundleContext() {
            return ;
        }
        @Override
        public String getFilter() {
            return ;
        }
        @Override
        public boolean isRemoved() {
            return ;
        }
        public void setRemoved(boolean removed) {
            this. = removed;
        }
        @Override
        public int hashCode() {
            return toString().hashCode();
        }
        @Override
        public boolean equals(Object obj) {
            // Two ListenerInfos are equals if they refer to the same listener for a given addition and removal life cycle.
            // If the same listener is added again, it must have a different ListenerInfo which is not equal to this
            // ListenerInfo.
            return super.equals(obj);
        }
        @Override
        public String toString() {
            String className = .getClass().getName();
            return "ListenerInfo[" +  + "," + className + "," +  + "]";
        }
    }
    static class FrameworkEventImpl extends FrameworkEvent {
        private static final long serialVersionUID = 6505331543651318189L;
        public FrameworkEventImpl(int typeBundle bundleThrowable throwable) {
            super(typebundlethrowable);
        }
        @Override
        public String toString() {
            return "FrameworkEvent[type=" + ConstantsHelper.frameworkEvent(getType()) + ",source=" + getSource() + "]";
        }
    }
    static class BundleEventImpl extends BundleEvent {
        private static final long serialVersionUID = -2705304702665185935L;
        public BundleEventImpl(int typeBundle bundle) {
            super(typebundle);
        }
        @Override
        public String toString() {
            return "BundleEvent[type=" + ConstantsHelper.bundleEvent(getType()) + ",source=" + getSource() + "]";
        }
    }
    static class ServiceEventImpl extends ServiceEvent {
        private static final long serialVersionUID = 62018288275708239L;
        public ServiceEventImpl(int typeServiceState serviceState) {
            super(typeserviceState.getReference());
        }
        @Override
        public String toString() {
            return "ServiceEvent[type=" + ConstantsHelper.serviceEvent(getType()) + ",source=" + getSource() + "]";
        }
    }
New to GrepCode? Check out our FAQ X