<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.framework;

import java.util.*;

import org.apache.felix.framework.util.FelixConstants;
import org.osgi.framework.*;
import org.osgi.framework.hooks.service.ListenerHook;

public class ServiceRegistry
{
    private Logger m_logger = null;
    private long m_currentServiceId = 1L;
    // Maps bundle to an array of service registrations.
    private Map m_serviceRegsMap = new HashMap();
    // Maps registration to thread to keep track when a
    // registration is in use, which will cause other
    // threads to wait.
    private Map m_lockedRegsMap = new HashMap();
    // Maps bundle to an array of usage counts.
    private Map m_inUseMap = new HashMap();

    private ServiceListener m_serviceListener = null;

    private final List m_listenerHooks = new ArrayList();

    public ServiceRegistry(Logger logger)
    {
        m_logger = logger;
    }

    public synchronized ServiceReference[] getRegisteredServices(Bundle bundle)
    {
        ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
        if (regs != null)
        {
            ServiceReference[] refs = new ServiceReference[regs.length];
            for (int i = 0; i < refs.length; i++)
            {
                refs[i] = regs[i].getReference();
            }
            return refs;
        }
        return null;
    }

    public ServiceRegistration registerService(
        Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
    {
        ServiceRegistration reg = null;

        synchronized (this)
        {
            // Keep track of registered hooks.
            addHooks(classNames, svcObj);

            // Create the service registration.
            reg = new ServiceRegistrationImpl(
                this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict);
            // Get the bundles current registered services.
            ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
            m_serviceRegsMap.put(bundle, addServiceRegistration(regs, reg));
        }
        fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
        return reg;
    }

    public void unregisterService(Bundle bundle, ServiceRegistration reg)
    {
        // If this is a hook, it should be removed.
        removeHook(((ServiceRegistrationImpl) reg).getService());

        synchronized (this)
        {
            // Note that we don't lock the service registration here using
            // the m_lockedRegsMap because we want to allow bundles to get
            // the service during the unregistration process. However, since
            // we do remove the registration from the service registry, no
            // new bundles will be able to look up the service.

            // Now remove the registered service.
            ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
            m_serviceRegsMap.put(bundle, removeServiceRegistration(regs, reg));
        }

        // Fire the service event which gives all client bundles the
        // opportunity to unget their service object.
        fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));

        // Now forcibly unget the service object for all stubborn clients.
        synchronized (this)
        {
            Bundle[] clients = getUsingBundles(reg.getReference());
            for (int i = 0; (clients != null) && (i < clients.length); i++)
            {
                while (ungetService(clients[i], reg.getReference()))
                    ; // Keep removing until it is no longer possible
            }
            ((ServiceRegistrationImpl) reg).invalidate();
        }
    }

    /**
     * This method retrieves all services registrations for the specified
     * bundle and invokes <tt>ServiceRegistration.unregister()</tt> on each
     * one. This method is only called be the framework to clean up after
     * a stopped bundle.
     * @param bundle the bundle whose services should be unregistered.
    **/
    public void unregisterServices(Bundle bundle)
    {
        // Simply remove all service registrations for the bundle.
        ServiceRegistration[] regs = null;
        synchronized (this)
        {
            regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
        }

        // Note, there is no race condition here with respect to the
        // bundle registering more services, because its bundle context
        // has already been invalidated by this point, so it would not
        // be able to register more services.

        // Unregister each service.
        for (int i = 0; (regs != null) && (i < regs.length); i++)
        {
            regs[i].unregister();
        }

        // Now remove the bundle itself.
        synchronized (this)<commit_msg>When unregistering all services for a bundle, verify each registration is valid before unregistering, since it is possible that an event from a subsequent unregister caused the unregistering of another service. (FELIX-952)<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.framework;

import java.util.*;

import org.apache.felix.framework.util.FelixConstants;
import org.osgi.framework.*;
import org.osgi.framework.hooks.service.ListenerHook;

public class ServiceRegistry
{
    private Logger m_logger = null;
    private long m_currentServiceId = 1L;
    // Maps bundle to an array of service registrations.
    private Map m_serviceRegsMap = new HashMap();
    // Maps registration to thread to keep track when a
    // registration is in use, which will cause other
    // threads to wait.
    private Map m_lockedRegsMap = new HashMap();
    // Maps bundle to an array of usage counts.
    private Map m_inUseMap = new HashMap();

    private ServiceListener m_serviceListener = null;

    private final List m_listenerHooks = new ArrayList();

    public ServiceRegistry(Logger logger)
    {
        m_logger = logger;
    }

    public synchronized ServiceReference[] getRegisteredServices(Bundle bundle)
    {
        ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
        if (regs != null)
        {
            ServiceReference[] refs = new ServiceReference[regs.length];
            for (int i = 0; i < refs.length; i++)
            {
                refs[i] = regs[i].getReference();
            }
            return refs;
        }
        return null;
    }

    public ServiceRegistration registerService(
        Bundle bundle, String[] classNames, Object svcObj, Dictionary dict)
    {
        ServiceRegistration reg = null;

        synchronized (this)
        {
            // Keep track of registered hooks.
            addHooks(classNames, svcObj);

            // Create the service registration.
            reg = new ServiceRegistrationImpl(
                this, bundle, classNames, new Long(m_currentServiceId++), svcObj, dict);
            // Get the bundles current registered services.
            ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
            m_serviceRegsMap.put(bundle, addServiceRegistration(regs, reg));
        }
        fireServiceChanged(new ServiceEvent(ServiceEvent.REGISTERED, reg.getReference()));
        return reg;
    }

    public void unregisterService(Bundle bundle, ServiceRegistration reg)
    {
        // If this is a hook, it should be removed.
        removeHook(((ServiceRegistrationImpl) reg).getService());

        synchronized (this)
        {
            // Note that we don't lock the service registration here using
            // the m_lockedRegsMap because we want to allow bundles to get
            // the service during the unregistration process. However, since
            // we do remove the registration from the service registry, no
            // new bundles will be able to look up the service.

            // Now remove the registered service.
            ServiceRegistration[] regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
            m_serviceRegsMap.put(bundle, removeServiceRegistration(regs, reg));
        }

        // Fire the service event which gives all client bundles the
        // opportunity to unget their service object.
        fireServiceChanged(new ServiceEvent(ServiceEvent.UNREGISTERING, reg.getReference()));

        // Now forcibly unget the service object for all stubborn clients.
        synchronized (this)
        {
            Bundle[] clients = getUsingBundles(reg.getReference());
            for (int i = 0; (clients != null) && (i < clients.length); i++)
            {
                while (ungetService(clients[i], reg.getReference()))
                    ; // Keep removing until it is no longer possible
            }
            ((ServiceRegistrationImpl) reg).invalidate();
        }
    }

    /**
     * This method retrieves all services registrations for the specified
     * bundle and invokes <tt>ServiceRegistration.unregister()</tt> on each
     * one. This method is only called be the framework to clean up after
     * a stopped bundle.
     * @param bundle the bundle whose services should be unregistered.
    **/
    public void unregisterServices(Bundle bundle)
    {
        // Simply remove all service registrations for the bundle.
        ServiceRegistration[] regs = null;
        synchronized (this)
        {
            regs = (ServiceRegistration[]) m_serviceRegsMap.get(bundle);
        }

        // Note, there is no race condition here with respect to the
        // bundle registering more services, because its bundle context
        // has already been invalidated by this point, so it would not
        // be able to register more services.

        // Unregister each service.
        for (int i = 0; (regs != null) && (i < regs.length); i++)
        {
            if (((ServiceRegistrationImpl) regs[i]).isValid())
            {
                regs[i].unregister();
            }
        }

        // Now remove the bundle itself.
        synchronized (this)
{'fraction_non_alphanumeric': 0.08084343520573672, 'fraction_numerical': 0.0016219907802629333, 'mean_word_length': 2.445588235294118, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4671472', 'n_tokens_mistral': 2898, 'n_tokens_neox': 2827, 'n_words': 1103}