<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.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.apache.felix.framework.capabilityset.Capability;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.Directive;
import org.apache.felix.framework.resolver.Module;
import org.apache.felix.framework.capabilityset.Requirement;
import org.apache.felix.framework.resolver.Wire;
import org.apache.felix.framework.resolver.CandidateComparator;
import org.apache.felix.framework.resolver.ResolveException;
import org.apache.felix.framework.resolver.Resolver;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.R4Library;
import org.osgi.framework.BundlePermission;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;

public class FelixResolverState implements Resolver.ResolverState
{
    private final Logger m_logger;
    // List of all modules.
    private final List<Module> m_modules;
    // Capability sets.
    private final Map<String, CapabilitySet> m_capSets;
    // Maps fragment symbolic names to list of fragment modules sorted by version.
    private final Map<String, List<Module>> m_fragmentMap = new HashMap<String, List<Module>>();
    // Maps singleton symbolic names to list of modules sorted by version.
    private final Map<String, List<Module>> m_singletons = new HashMap<String, List<Module>>();
    // Execution environment.
    private final String m_fwkExecEnvStr;
    // Parsed framework environments
    private final Set<String> m_fwkExecEnvSet;

    public FelixResolverState(Logger logger, String fwkExecEnvStr)
    {
        m_logger = logger;
        m_modules = new ArrayList<Module>();
        m_capSets = new HashMap<String, CapabilitySet>();

        m_fwkExecEnvStr = (fwkExecEnvStr != null) ? fwkExecEnvStr.trim() : null;
        m_fwkExecEnvSet = parseExecutionEnvironments(fwkExecEnvStr);

        List<String> indices = new ArrayList<String>();
        indices.add(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
        m_capSets.put(Capability.MODULE_NAMESPACE, new CapabilitySet(indices, true));

        indices = new ArrayList<String>();
        indices.add(Capability.PACKAGE_ATTR);
        m_capSets.put(Capability.PACKAGE_NAMESPACE, new CapabilitySet(indices, true));

        indices = new ArrayList<String>();
        indices.add(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
        m_capSets.put(Capability.HOST_NAMESPACE,  new CapabilitySet(indices, true));
    }

    public synchronized void addModule(Module module)
    {
        if (isSingleton(module))
        {
            // Find the currently selected singleton, which is either the
            // highest version or the resolved one.
            List<Module> modules = m_singletons.get(module.getSymbolicName());
            // Get the highest version.
            Module current = ((modules != null) && !modules.isEmpty()) ? modules.get(0) : null;
            // Now check to see if there is a resolved one instead.
            for (int i = 0; (modules != null) && (i < modules.size()); i++)
            {
                if (modules.get(i).isResolved())
                {
                    current = modules.get(i);
                }
            }

            // Index the new singleton.
            Module highest = indexModule(m_singletons, module);
            // If the currently selected singleton is not resolved and
            // the newly added singleton is a higher version, then select
            // it instead.
            if ((current != null) && !current.isResolved() && (current != highest))
            {
                if (Util.isFragment(current))
                {
                    removeFragment(current);
                }
                else
                {
                    removeHost(current);
                }
            }
            else if (current != null)
            {
                module = null;
            }
        }

        if ((module != null) && Util.isFragment(module))
        {
            addFragment(module);
        }
        else if (module != null)
        {
            addHost(module);
        }
    }

    public synchronized void removeModule(Module module)
    {
        // If this module is a singleton, then remove it from the
        // singleton map.
        List<Module> modules = m_singletons.get(module.getSymbolicName());
        if (modules != null)
        {
            modules.remove(module);
            if (modules.isEmpty())
            {
                m_singletons.remove(module.getSymbolicName());
            }
        }

        if (Util.isFragment(module))
        {
            removeFragment(module);
        }
        else
        {
            removeHost(module);
        }
    }

    public void detachFragment(Module host, Module fragment)
    {
        List<Module> fragments = ((ModuleImpl) host).getFragments();
        fragments.remove(fragment);
        try
        {
            ((ModuleImpl) host).attachFragments(fragments);
        }
        catch (Exception ex)
        {
            // Try to clean up by removing all fragments.
            try
            {
                ((ModuleImpl) host).attachFragments(null);
            }
            catch (Exception ex2)
            {
                // Ignore
            }
            m_logger.log(host.getBundle(), Logger.LOG_ERROR,
                "Serious error attaching fragments.", ex);<commit_msg>[FELIX-2851] Resolution problems after a fragment can't be resolved<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.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import org.apache.felix.framework.capabilityset.Capability;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.Directive;
import org.apache.felix.framework.resolver.Module;
import org.apache.felix.framework.capabilityset.Requirement;
import org.apache.felix.framework.resolver.Wire;
import org.apache.felix.framework.resolver.CandidateComparator;
import org.apache.felix.framework.resolver.ResolveException;
import org.apache.felix.framework.resolver.Resolver;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.R4Library;
import org.osgi.framework.BundlePermission;
import org.osgi.framework.PackagePermission;
import org.osgi.framework.Constants;
import org.osgi.framework.Version;

public class FelixResolverState implements Resolver.ResolverState
{
    private final Logger m_logger;
    // List of all modules.
    private final List<Module> m_modules;
    // Capability sets.
    private final Map<String, CapabilitySet> m_capSets;
    // Maps fragment symbolic names to list of fragment modules sorted by version.
    private final Map<String, List<Module>> m_fragmentMap = new HashMap<String, List<Module>>();
    // Maps singleton symbolic names to list of modules sorted by version.
    private final Map<String, List<Module>> m_singletons = new HashMap<String, List<Module>>();
    // Execution environment.
    private final String m_fwkExecEnvStr;
    // Parsed framework environments
    private final Set<String> m_fwkExecEnvSet;

    public FelixResolverState(Logger logger, String fwkExecEnvStr)
    {
        m_logger = logger;
        m_modules = new ArrayList<Module>();
        m_capSets = new HashMap<String, CapabilitySet>();

        m_fwkExecEnvStr = (fwkExecEnvStr != null) ? fwkExecEnvStr.trim() : null;
        m_fwkExecEnvSet = parseExecutionEnvironments(fwkExecEnvStr);

        List<String> indices = new ArrayList<String>();
        indices.add(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
        m_capSets.put(Capability.MODULE_NAMESPACE, new CapabilitySet(indices, true));

        indices = new ArrayList<String>();
        indices.add(Capability.PACKAGE_ATTR);
        m_capSets.put(Capability.PACKAGE_NAMESPACE, new CapabilitySet(indices, true));

        indices = new ArrayList<String>();
        indices.add(Constants.BUNDLE_SYMBOLICNAME_ATTRIBUTE);
        m_capSets.put(Capability.HOST_NAMESPACE,  new CapabilitySet(indices, true));
    }

    public synchronized void addModule(Module module)
    {
        if (isSingleton(module))
        {
            // Find the currently selected singleton, which is either the
            // highest version or the resolved one.
            List<Module> modules = m_singletons.get(module.getSymbolicName());
            // Get the highest version.
            Module current = ((modules != null) && !modules.isEmpty()) ? modules.get(0) : null;
            // Now check to see if there is a resolved one instead.
            for (int i = 0; (modules != null) && (i < modules.size()); i++)
            {
                if (modules.get(i).isResolved())
                {
                    current = modules.get(i);
                }
            }

            // Index the new singleton.
            Module highest = indexModule(m_singletons, module);
            // If the currently selected singleton is not resolved and
            // the newly added singleton is a higher version, then select
            // it instead.
            if ((current != null) && !current.isResolved() && (current != highest))
            {
                if (Util.isFragment(current))
                {
                    removeFragment(current);
                }
                else
                {
                    removeHost(current);
                }
            }
            else if (current != null)
            {
                module = null;
            }
        }

        if ((module != null) && Util.isFragment(module))
        {
            addFragment(module);
        }
        else if (module != null)
        {
            addHost(module);
        }
    }

    public synchronized void removeModule(Module module)
    {
        // If this module is a singleton, then remove it from the
        // singleton map.
        List<Module> modules = m_singletons.get(module.getSymbolicName());
        if (modules != null)
        {
            modules.remove(module);
            if (modules.isEmpty())
            {
                m_singletons.remove(module.getSymbolicName());
            }
        }

        if (Util.isFragment(module))
        {
            removeFragment(module);
        }
        else
        {
            removeHost(module);
        }
    }

    public void detachFragment(Module host, Module fragment)
    {
        List<Module> fragments = new ArrayList<Module>(((ModuleImpl) host).getFragments());
        fragments.remove(fragment);
        removeFragment(fragment);
        try
        {
            ((ModuleImpl) host).attachFragments(fragments);
        }
        catch (Exception ex)
        {
            // Try to clean up by removing all fragments.
            try
            {
                ((ModuleImpl) host).attachFragments(null);
            }
            catch (Exception ex2)
            {
                // Ignore
            }
            m_logger.log(host.getBundle(), Logger.LOG_ERROR,
                "Serious error attaching fragments.", ex);
{'fraction_non_alphanumeric': 0.09420234937476317, 'fraction_numerical': 0.0015157256536566881, 'mean_word_length': 2.3205837946653247, 'pattern_counts': {'":': 0, '<': 46, '<?xml version=': 0, '>': 44, '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': '18877', 'n_tokens_mistral': 3513, 'n_tokens_neox': 3425, 'n_words': 955}