FELIX-4729 Added ability to convert Bundle-NativeCode to Require-Capability as defined in R6 spec.

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1646550 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
index 9ce710b..151c8fb 100644
--- a/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/framework/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -35,8 +35,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 import java.util.NoSuchElementException;
 import java.util.Set;
 
@@ -47,6 +45,7 @@
 import org.apache.felix.framework.util.Util;
 import org.apache.felix.framework.util.manifestparser.ManifestParser;
 import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.util.manifestparser.R4LibraryClause;
 import org.apache.felix.framework.wiring.BundleCapabilityImpl;
 import org.apache.felix.framework.wiring.BundleWireImpl;
 import org.osgi.framework.AdminPermission;
@@ -253,26 +252,24 @@
         String osVersion = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
         String userLang = (String)m_configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
         Map<String, Object> attributes = new HashMap<String, Object>();
+        
+        //Add all startup properties so we can match selection-filters
+        attributes.putAll(m_configMap);
 
         if( osArchitecture != null )
         {
-            attributes.put(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, osArchitecture);
+            attributes.put(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, R4LibraryClause.getProcessorWithAliases(osArchitecture));
         }
 
         if( osName != null)
         {
-            attributes.put(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, osName);
+            attributes.put(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, R4LibraryClause.getOsNameWithAliases(osName));
         }
 
         if( osVersion != null)
         {
-            Pattern versionPattern = Pattern.compile("\\d+\\.?\\d*\\.?\\d*");
-            Matcher matcher = versionPattern.matcher(osVersion);
-            if(matcher.find())
-            {
-                osVersion = matcher.group();
-            }
-            attributes.put(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, new Version(osVersion));
+            osVersion = R4LibraryClause.formatOSVersion(osVersion);
+            attributes.put(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, Version.parseVersion(osVersion));
         }
 
         if( userLang != null)
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
index 672fd2f..1cf00b2 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
@@ -19,6 +19,7 @@
 package org.apache.felix.framework.util.manifestparser;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -41,6 +42,7 @@
 import org.osgi.framework.namespace.BundleNamespace;
 import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
 import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
 import org.osgi.framework.wiring.BundleCapability;
 import org.osgi.framework.wiring.BundleRequirement;
 import org.osgi.framework.wiring.BundleRevision;
@@ -243,24 +245,6 @@
             exportCaps = calculateImplicitUses(exportCaps, allImportClauses);
         }
 
-        // Combine all capabilities.
-        m_capabilities = new ArrayList(
-             capList.size() + exportCaps.size() + provideCaps.size());
-        m_capabilities.addAll(capList);
-        m_capabilities.addAll(exportCaps);
-        m_capabilities.addAll(provideCaps);
-
-        // Combine all requirements.
-        m_requirements = new ArrayList(
-            hostReqs.size() + importReqs.size() + rbReqs.size()
-            + requireReqs.size() + dynamicReqs.size() + breeReqs.size());
-        m_requirements.addAll(hostReqs);
-        m_requirements.addAll(importReqs);
-        m_requirements.addAll(rbReqs);
-        m_requirements.addAll(requireReqs);
-        m_requirements.addAll(dynamicReqs);
-        m_requirements.addAll(breeReqs);
-
         //
         // Parse Bundle-NativeCode.
         //
@@ -279,6 +263,27 @@
             m_libraryHeadersOptional = true;
             m_libraryClauses.remove(m_libraryClauses.size() - 1);
         }
+        
+        List<BundleRequirement> nativeCodeReqs = convertNativeCode(owner, m_libraryClauses, m_libraryHeadersOptional);
+        
+        // Combine all requirements.
+        m_requirements = new ArrayList(
+            hostReqs.size() + importReqs.size() + rbReqs.size()
+            + requireReqs.size() + dynamicReqs.size() + breeReqs.size());
+        m_requirements.addAll(hostReqs);
+        m_requirements.addAll(importReqs);
+        m_requirements.addAll(rbReqs);
+        m_requirements.addAll(requireReqs);
+        m_requirements.addAll(dynamicReqs);
+        m_requirements.addAll(breeReqs);
+        m_requirements.addAll(nativeCodeReqs);
+        
+        // Combine all capabilities.
+        m_capabilities = new ArrayList(
+             capList.size() + exportCaps.size() + provideCaps.size());
+        m_capabilities.addAll(capList);
+        m_capabilities.addAll(exportCaps);
+        m_capabilities.addAll(provideCaps);
 
         //
         // Parse activation policy.
@@ -601,6 +606,123 @@
 
         return reqList;
     }
+    
+    static List<BundleRequirement> convertNativeCode(BundleRevision owner, List<R4LibraryClause> nativeLibraryClauses, boolean hasOptionalLibraryDirective)
+    {
+        List<BundleRequirement> result = new ArrayList<BundleRequirement>();
+        
+        List<SimpleFilter> nativeFilterClauseList = new ArrayList<SimpleFilter>();
+        
+        if(nativeLibraryClauses != null)
+        {
+            for(R4LibraryClause clause: nativeLibraryClauses)
+            {
+                String[] osNameArray = clause.getOSNames();
+                String[] osVersionArray = clause.getOSVersions();
+                String[] processorArray = clause.getProcessors();
+                String[] languageArray = clause.getLanguages();
+                
+                String currentSelectionFilter = clause.getSelectionFilter();
+                
+                List<SimpleFilter> nativeFilterList = new ArrayList<SimpleFilter>();
+                if(osNameArray != null && osNameArray.length > 0)
+                {
+                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, osNameArray, SimpleFilter.APPROX));
+                }
+                
+                if(osVersionArray != null && osVersionArray.length > 0)
+                {
+                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, osVersionArray, SimpleFilter.EQ));
+                }
+                
+                if(processorArray != null && processorArray.length > 0)
+                {
+                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, processorArray, SimpleFilter.APPROX));
+                }
+
+                if(languageArray != null && languageArray.length > 0)
+                {
+                    nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, languageArray, SimpleFilter.APPROX));
+                }
+                
+                if(currentSelectionFilter != null)
+                {
+                    nativeFilterList.add(SimpleFilter.parse(currentSelectionFilter));
+                }
+                
+                if(!nativeFilterList.isEmpty())
+                {
+                    SimpleFilter nativeClauseFilter = new SimpleFilter(null, nativeFilterList, SimpleFilter.AND);
+                    nativeFilterClauseList.add(nativeClauseFilter);
+                }
+            }
+            
+            Map<String, String> requirementDirectives = new HashMap<String, String>();
+            
+            SimpleFilter consolidatedNativeFilter = null;
+            
+            if(hasOptionalLibraryDirective)
+            {
+                requirementDirectives.put(NativeNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, NativeNamespace.RESOLUTION_OPTIONAL);
+            }
+            
+            if(nativeFilterClauseList.size() > 1)
+            {
+                consolidatedNativeFilter = new SimpleFilter(null, nativeFilterClauseList, SimpleFilter.OR);
+                
+                requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
+            }
+            else if(nativeFilterClauseList.size() == 1)
+            {
+                consolidatedNativeFilter = nativeFilterClauseList.get(0);
+                
+                requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
+            }
+            
+            if(requirementDirectives.size() > 0)
+            {
+                result.add(new BundleRequirementImpl(owner, NativeNamespace.NATIVE_NAMESPACE, requirementDirectives,
+                        Collections.<String, Object>emptyMap(),
+                        consolidatedNativeFilter));
+            }
+            
+        }
+        
+        return result;
+    }
+    
+    private static SimpleFilter buildFilterFromArray(String attributeName, String[] stringArray, int operation)
+    {
+        SimpleFilter result = null;
+        List<SimpleFilter> filterSet = new ArrayList<SimpleFilter>();
+        
+        if(stringArray != null)
+        {
+            for(String currentValue : stringArray)
+            {
+                filterSet.add(new SimpleFilter(attributeName, currentValue.toLowerCase(), operation));
+            }
+            
+            if(filterSet.size() == 1)
+            {
+                result = filterSet.get(0);
+            }
+            else
+            {
+                result = new SimpleFilter(null, filterSet, SimpleFilter.OR);
+            }
+        }
+        
+        return result;
+    }
+    
+    private static void addStringArrayToSet(String[] array, Set<String> set)
+    {
+        if(array != null)
+        {
+            set.addAll(Arrays.asList(array));
+        }
+    }
 
     private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
         Logger logger, List<ParsedHeaderClause> clauses, String mv)
@@ -722,6 +844,14 @@
                         + path
                         + "' namespace.");
                 }
+                
+                if(path.startsWith(NativeNamespace.NATIVE_NAMESPACE) && (owner == null ||
+                        !FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(owner.getSymbolicName())))
+                {
+                    throw new BundleException("Only System Bundle can use Provide-Capability for '"
+                            + path
+                            + "' namespace.", BundleException.MANIFEST_ERROR);
+                }
 
                 // Create package capability and add to capability list.
                 capList.add(
diff --git a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
index 769c214..b59d18b 100644
--- a/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
+++ b/framework/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
@@ -19,14 +19,19 @@
 package org.apache.felix.framework.util.manifestparser;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Dictionary;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import org.apache.felix.framework.Logger;
 import org.apache.felix.framework.util.FelixConstants;
@@ -41,10 +46,12 @@
 {
     private static final String OS_AIX = "aix";
     private static final String OS_DIGITALUNIX = "digitalunix";
+    private static final String OS_EPOC = "epoc32";
     private static final String OS_HPUX = "hpux";
     private static final String OS_IRIX = "irix";
     private static final String OS_LINUX = "linux";
     private static final String OS_MACOS = "macos";
+    private static final String OS_MACOSX = "macosx";
     private static final String OS_NETBSD = "netbsd";
     private static final String OS_NETWARE = "netware";
     private static final String OS_OPENBSD = "openbsd";
@@ -67,6 +74,19 @@
     private static final String OS_WINDOWS_VISTA = "windowsvista";
     private static final String OS_WINDOWS_XP = "windowsxp";
     private static final String OS_WIN_32 = "win32";
+    
+    private static final String PROC_X86_64 = "x86-64";
+    private static final String PROC_X86 = "x86";
+    private static final String PROC_68K = "68k";
+    private static final String PROC_ARM_LE = "arm_le";
+    private static final String PROC_ARM_BE = "arm_be";
+    private static final String PROC_ARM = "arm";
+    private static final String PROC_ALPHA = "alpha";
+    private static final String PROC_IGNITE = "ignite";
+    private static final String PROC_MIPS = "mips";
+    private static final String PROC_PARISC = "parisc";
+    private static final String PROC_POWER_PC = "powerpc";
+    private static final String PROC_SPARC = "sparc";
 
     /* Storing the OS names in a map as this is quicker to look up than a list.
      */
@@ -127,12 +147,9 @@
 
     public R4LibraryClause(R4LibraryClause library)
     {
-        m_libraryEntries = library.m_libraryEntries;
-        m_osnames = library.m_osnames;
-        m_osversions = library.m_osversions;
-        m_processors = library.m_processors;
-        m_languages = library.m_languages;
-        m_selectionFilter = library.m_selectionFilter;
+        this(library.m_libraryEntries, library.m_osnames, library.m_osversions,
+            library.m_processors, library.m_languages,
+            library.m_selectionFilter);
     }
 
     public String[] getLibraryEntries()
@@ -167,19 +184,19 @@
 
     public boolean match(Map configMap) throws BundleException
     {
-        String normal_osname = normalizeOSName((String) configMap.get(Constants.FRAMEWORK_OS_NAME));
-        String normal_processor = normalizeProcessor((String) configMap.get(Constants.FRAMEWORK_PROCESSOR));
-        String normal_osversion = normalizeOSVersion((String) configMap.get(Constants.FRAMEWORK_OS_VERSION));
-        String normal_language = (String) configMap.get(Constants.FRAMEWORK_LANGUAGE);
+        String osName = (String) configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
+        String processorName = (String) configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
+        String osVersion = (String) configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
+        String language = (String) configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
 
         // Check library's osname.
-        if (!checkOSNames(normal_osname, getOSNames()))
+        if (!checkOSNames(osName, getOSNames()))
         {
             return false;
         }
 
         // Check library's processor.
-        if (!checkProcessors(normal_processor, getProcessors()))
+        if (!checkProcessors(processorName, getProcessors()))
         {
             return false;
         }
@@ -187,7 +204,7 @@
         // Check library's osversion if specified.
         if ((getOSVersions() != null) &&
             (getOSVersions().length > 0) &&
-            !checkOSVersions(normal_osversion, getOSVersions()))
+            !checkOSVersions(osVersion, getOSVersions()))
         {
             return false;
         }
@@ -195,7 +212,7 @@
         // Check library's language if specified.
         if ((getLanguages() != null) &&
             (getLanguages().length > 0) &&
-            !checkLanguages(normal_language, getLanguages()))
+            !checkLanguages(language, getLanguages()))
         {
             return false;
         }
@@ -211,42 +228,49 @@
         return true;
     }
 
-    private boolean checkOSNames(String currentOSName, String[] osnames)
+    private boolean checkOSNames(String osName, String[] osnames)
     {
-        boolean win32 = currentOSName.startsWith("win") && !currentOSName.equals(OS_WINDOWS_CE);
-
-        for (int i = 0; (osnames != null) && (i < osnames.length); i++)
+        List<String> capabilityOsNames = getOsNameWithAliases(osName);
+        if (capabilityOsNames != null && osnames != null)
         {
-            if (osnames[i].equals(currentOSName) ||
-                (OS_WIN_32.equals(osnames[i]) && win32))
+            for (String curOsName : osnames)
             {
-                return true;
+                if (capabilityOsNames.contains(curOsName))
+                {
+                    return true;
+                }
+
             }
         }
         return false;
     }
 
-    private boolean checkProcessors(String currentProcessor, String[] processors)
+    private boolean checkProcessors(String processorName, String[] processors)
     {
-        for (int i = 0; (processors != null) && (i < processors.length); i++)
+        List<String> capabilitiesProcessors = getProcessorWithAliases(processorName);
+        if (capabilitiesProcessors != null && processors != null)
         {
-            if (processors[i].equals(currentProcessor))
+            for (String currentProcessor : processors)
             {
-                return true;
+                if (capabilitiesProcessors.contains(currentProcessor))
+                {
+                    return true;
+                }
             }
         }
         return false;
     }
 
-    private boolean checkOSVersions(String currentOSVersion, String[] osversions)
+    private boolean checkOSVersions(String osVersion, String[] osversions) 
         throws BundleException
     {
+        Version currentOSVersion = Version.parseVersion(formatOSVersion(osVersion));
         for (int i = 0; (osversions != null) && (i < osversions.length); i++)
         {
             try
             {
                 VersionRange range = VersionRange.parse(osversions[i]);
-                if (range.isInRange(new Version(currentOSVersion)))
+                if (range.isInRange(currentOSVersion))
                 {
                     return true;
                 }
@@ -304,6 +328,7 @@
                 return null;
             }
 
+            s = s.trim();
             if (s.equals(FelixConstants.BUNDLE_NATIVECODE_OPTIONAL))
             {
                 return new R4LibraryClause(null, null, null, null, null, null);
@@ -368,10 +393,16 @@
                             value = value.substring(1);
                         }
                     }
+
+                    if (value != null)
+                    {
+                        value = value.toLowerCase();
+                    }
+
                     // Add the value to its corresponding property list.
                     if (property.equals(Constants.BUNDLE_NATIVECODE_OSNAME))
                     {
-                        osNameList.add(normalizeOSName(value));
+                        osNameList.add(value);
                     }
                     else if (property.equals(Constants.BUNDLE_NATIVECODE_OSVERSION))
                     {
@@ -379,7 +410,7 @@
                     }
                     else if (property.equals(Constants.BUNDLE_NATIVECODE_PROCESSOR))
                     {
-                        processorList.add(normalizeProcessor(value));
+                        processorList.add(value);
                     }
                     else if (property.equals(Constants.BUNDLE_NATIVECODE_LANGUAGE))
                     {
@@ -387,7 +418,7 @@
                     }
                     else if (property.equals(Constants.SELECTION_FILTER_ATTRIBUTE))
                     {
-// TODO: NATIVE - I believe we can have multiple selection filters too.
+                        // TODO: NATIVE - I believe we can have multiple selection filters too.
                         selectionFilter = value;
                     }
                 }
@@ -417,6 +448,250 @@
         }
     }
 
+    public static String formatOSVersion(String value)
+    {
+        // Header: 'Bundle-NativeCode', Parameter: 'osversion'
+        // Standardized 'osversion': major.minor.micro, only digits
+        try
+        {
+            Pattern versionPattern = Pattern.compile("\\d+\\.?\\d*\\.?\\d*");
+            Matcher matcher = versionPattern.matcher(value);
+            if (matcher.find())
+            {
+                value = matcher.group();
+            }
+            return Version.parseVersion(value).toString();
+        }
+        catch (Exception ex)
+        {
+            return Version.emptyVersion.toString();
+        }
+    }
+
+    public static List<String> getOsNameWithAliases(String osName)
+    {
+        //Can't assume this has been normalized
+        osName = normalizeOSName(osName);
+
+        List<String> result = null;
+        // 
+        if (osName.startsWith("win"))
+        {
+            // Per spec windows ce does not include win32 alias
+            if (osName.equals(OS_WINDOWS_CE))
+            {
+                result = Arrays.asList("windowsce", "wince", "windows ce");
+            }
+            else
+            {
+                //Accumulate windows aliases.  win32 may match many versions of windows.
+                Set<String> windowsOsList = new HashSet<String>();
+
+                if (osName.equals(OS_WINDOWS_95)|| osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows95", "win95",
+                        "windows 95", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_98) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows98",
+                        "windows 98", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_NT) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windowsnt", "winnt",
+                        "windows nt", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_2000) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows2000",
+                        "win2000", "windows 2000", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_2003) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows2003",
+                        "win2003", "windows 2003", OS_WIN_32,
+                        "windows server 2003", "windowsserver2003"));
+                }
+
+                if (osName.equals(OS_WINDOWS_SERVER_2008) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows2008",
+                        "win2008", "windows 2008", OS_WIN_32,
+                        "windows server 2008", "windowsserver2008"));
+                }
+
+                if (osName.equals(OS_WINDOWS_SERVER_2012) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows2012",
+                        "win2012", "windows 2012", OS_WIN_32,
+                        "windows server 2012", "windowsserver2012"));
+                }
+
+                if (osName.equals(OS_WINDOWS_XP) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windowsxp", "winxp",
+                        "windows xp", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_VISTA) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windowsvista",
+                        "windows vista", OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_7) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows7", "windows 7",
+                        OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_8) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows8", "windows 8",
+                        OS_WIN_32));
+                }
+
+                if (osName.equals(OS_WINDOWS_9) || osName.equals(OS_WIN_32))
+                {
+                    windowsOsList.addAll(Arrays.asList("windows9", "windows 9",
+                        OS_WIN_32));
+                }
+
+                if (windowsOsList.isEmpty())
+                {
+                    windowsOsList.add(osName);
+                }
+                result = new ArrayList<String>(windowsOsList);
+            }
+
+        }
+        else if (osName.equals(OS_LINUX))
+        {
+            result = Collections.singletonList(OS_LINUX);
+        }
+        else if (osName.equals(OS_AIX))
+        {
+            result = Collections.singletonList(OS_AIX);
+        }
+        else if (osName.equals(OS_DIGITALUNIX))
+        {
+            result = Collections.singletonList(OS_DIGITALUNIX);
+        }
+        else if (osName.equals(OS_EPOC))
+        {
+            result = Arrays.asList(OS_EPOC, "symbianos");
+        }
+        else if (osName.equals(OS_HPUX))
+        {
+            result = Arrays.asList(OS_HPUX, "hp-ux");
+        }
+        else if (osName.equals(OS_IRIX))
+        {
+            result = Collections.singletonList(OS_IRIX);
+        }
+        else if (osName.equals(OS_MACOSX))
+        {
+            result = Arrays.asList(OS_MACOSX, "mac os x");
+        }
+        else if (osName.equals(OS_MACOS))
+        {
+            result = Arrays.asList(OS_MACOS, "mac os");
+        }
+        else if (osName.equals(OS_NETWARE))
+        {
+            result = Collections.singletonList(OS_NETWARE);
+        }
+        else if (osName.equals(OS_OPENBSD))
+        {
+            result = Collections.singletonList(OS_OPENBSD);
+        }
+        else if (osName.equals(OS_NETBSD))
+        {
+            result = Collections.singletonList(OS_NETBSD);
+        }
+        else if (osName.equals(OS_OS2))
+        {
+            result = Arrays.asList(OS_OS2, "os/2");
+        }
+        else if (osName.equals(OS_QNX))
+        {
+            result = Arrays.asList(OS_QNX, "procnto");
+        }
+        else if (osName.equals(OS_SOLARIS))
+        {
+            result = Collections.singletonList(OS_SOLARIS);
+        }
+        else if (osName.equals(OS_SUNOS))
+        {
+            result = Collections.singletonList(OS_SUNOS);
+        }
+        else if (osName.equals(OS_VXWORKS))
+        {
+            result = Collections.singletonList(OS_VXWORKS);
+        }
+        else
+        {
+            result = Collections.singletonList(osName);
+        }
+
+        return Collections.unmodifiableList(result);
+    }
+
+    public static List<String> getProcessorWithAliases(String processor)
+    {
+        //Can't assume this has been normalized
+        processor = normalizeProcessor(processor);
+
+        List<String> result = null;
+        if (processor.equals(PROC_X86_64))
+        {
+            result = Arrays.asList(PROC_X86_64, "amd64", "em64t", "x86_64");
+        }
+        else if (processor.equals(PROC_X86))
+        {
+            result = Arrays.asList(PROC_X86, "pentium", "i386", "i486", "i586",
+                "i686");
+        }
+        else if (processor.equals(PROC_68K))
+        {
+            result = Arrays.asList(PROC_68K);
+        }
+        else if (processor.equals(PROC_ALPHA))
+        {
+            result = Arrays.asList(PROC_ALPHA);
+        }
+        else if (processor.equals(PROC_IGNITE))
+        {
+            result = Arrays.asList(PROC_IGNITE, "psc1k");
+        }
+        else if (processor.equals(PROC_MIPS))
+        {
+            result = Arrays.asList(PROC_MIPS);
+        }
+        else if (processor.equals(PROC_PARISC))
+        {
+            result = Arrays.asList(PROC_PARISC);
+        }
+        else if (processor.equals(PROC_POWER_PC))
+        {
+            result = Arrays.asList(PROC_POWER_PC, "power", "ppc");
+        }
+        else if (processor.equals(PROC_SPARC))
+        {
+            result = Arrays.asList(PROC_SPARC);
+        }
+        else
+        {
+            result = Collections.singletonList(processor);
+        }
+        return Collections.unmodifiableList(result);
+    }
+    
     public static String normalizeOSName(String value)
     {
         if (NORMALIZED_OS_NAMES.containsKey(value))
@@ -508,6 +783,10 @@
         {
             return OS_IRIX;
         }
+        else if (value.startsWith(OS_MACOSX) || value.startsWith("mac os x"))
+        {
+            return OS_MACOSX;
+        }
         else if (value.startsWith(OS_MACOS) || value.startsWith("mac os"))
         {
             return OS_MACOS;
@@ -551,49 +830,57 @@
     {
         value = value.toLowerCase();
 
-        if (value.startsWith("x86-64") || value.startsWith("amd64") ||
+        if (value.startsWith(PROC_X86_64) || value.startsWith("amd64") ||
             value.startsWith("em64") || value.startsWith("x86_64"))
         {
-            return "x86-64";
+            return PROC_X86_64;
         }
-        else if (value.startsWith("x86") || value.startsWith("pentium")
+        else if (value.startsWith(PROC_X86) || value.startsWith("pentium")
             || value.startsWith("i386") || value.startsWith("i486")
             || value.startsWith("i586") || value.startsWith("i686"))
         {
-            return "x86";
+            return PROC_X86;
         }
-        else if (value.startsWith("68k"))
+        else if (value.startsWith(PROC_68K))
         {
-            return "68k";
+            return PROC_68K;
         }
-        else if (value.startsWith("arm"))
+        else if (value.startsWith(PROC_ARM_LE))
         {
-            return "arm";
+            return PROC_ARM_LE;
         }
-        else if (value.startsWith("alpha"))
+        else if (value.startsWith(PROC_ARM_BE))
         {
-            return "alpha";
+            return PROC_ARM_BE;
         }
-        else if (value.startsWith("ignite") || value.startsWith("psc1k"))
+        else if (value.startsWith(PROC_ARM))
         {
-            return "ignite";
+            return PROC_ARM;
         }
-        else if (value.startsWith("mips"))
+        else if (value.startsWith(PROC_ALPHA))
         {
-            return "mips";
+            return PROC_ALPHA;
         }
-        else if (value.startsWith("parisc"))
+        else if (value.startsWith(PROC_IGNITE) || value.startsWith("psc1k"))
         {
-            return "parisc";
+            return PROC_IGNITE;
         }
-        else if (value.startsWith("powerpc") || value.startsWith("power")
+        else if (value.startsWith(PROC_MIPS))
+        {
+            return PROC_MIPS;
+        }
+        else if (value.startsWith(PROC_PARISC))
+        {
+            return PROC_PARISC;
+        }
+        else if (value.startsWith(PROC_POWER_PC) || value.startsWith("power")
             || value.startsWith("ppc"))
         {
-            return "powerpc";
+            return PROC_POWER_PC;
         }
-        else if (value.startsWith("sparc"))
+        else if (value.startsWith(PROC_SPARC))
         {
-            return "sparc";
+            return PROC_SPARC;
         }
         return value;
     }
diff --git a/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java b/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
index 63e4a79..a281562 100644
--- a/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
@@ -25,6 +25,8 @@
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.jar.JarOutputStream;
@@ -88,12 +90,12 @@
                         NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE));
         assertEquals(
                 "Native Processor should be same as framework Processor",
-                "x86_64",
+                Arrays.asList("x86-64", "amd64", "em64t", "x86_64"),
                 nativeBundleCapability.getAttributes().get(
                         NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE));
         assertEquals(
                 "Native OS Name should be the same as the framework os name",
-                "windows8",
+                Arrays.asList("windows8", "windows 8", "win32"),
                 nativeBundleCapability.getAttributes().get(
                         NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE));
         assertEquals(
diff --git a/framework/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java b/framework/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
index 194458d..3d826f4 100644
--- a/framework/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
@@ -18,19 +18,27 @@
  */
 package org.apache.felix.framework.util.manifestparser;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.mockito.Mockito.*;
 import junit.framework.TestCase;
 
+import org.apache.felix.framework.util.FelixConstants;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
 import org.osgi.framework.namespace.IdentityNamespace;
 import org.osgi.framework.namespace.NativeNamespace;
 import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
 
 public class ManifestParserTest extends TestCase
 {
@@ -80,14 +88,16 @@
 	public void testNativeCapability() throws BundleException {
         Map<String, String> headers = new HashMap<String, String>();
         headers.put(Constants.BUNDLE_MANIFESTVERSION,  "2");
-        headers.put(Constants.BUNDLE_SYMBOLICNAME, "foo.bar");
+        headers.put(Constants.BUNDLE_SYMBOLICNAME, FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
         headers.put(Constants.PROVIDE_CAPABILITY, " osgi.native;" +
         		"osgi.native.osname:List<String>=\"Windows7,Windows 7,Win7,Win32\";"+
         		"osgi.native.osversion:Version=\"7.0\";"+
         		"osgi.native.processor:List<String>=\"x86-64,amd64,em64t,x86_64\";"+
         		"osgi.native.language=\"en\"");
+        BundleRevision mockBundleRevision = mock(BundleRevision.class);
+        when(mockBundleRevision.getSymbolicName()).thenReturn(FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
     	
-        ManifestParser mp = new ManifestParser(null, null, null, headers);
+        ManifestParser mp = new ManifestParser(null, null, mockBundleRevision, headers);
 
         BundleCapability ic = findCapability(mp.getCapabilities(), NativeNamespace.NATIVE_NAMESPACE);
     	
@@ -99,6 +109,39 @@
         assertEquals(4, nativeProcesserList.size());
     
     }
+    
+    public void testConvertNativeCode() throws InvalidSyntaxException
+    {
+        List<R4LibraryClause> nativeLibraryClauses = new ArrayList<R4LibraryClause>();
+        String[] libraryFiles = {"lib/http.dll", "lib/zlib.dll"};
+        String[] osNames = {"Windows95", "Windows98", "WindowsNT"};
+        String[] processors = {"x86"};
+        String[] osVersions = null;
+        String[] languages = {"en", "se"};
+        String selectionFilter = "(com.acme.windowing=win32)";
+        R4LibraryClause clause = new R4LibraryClause(libraryFiles, osNames, processors, osVersions, languages, selectionFilter);
+        BundleRevision owner = mock(BundleRevision.class);
+        nativeLibraryClauses.add(clause);
+        
+        List<BundleRequirement> nativeBundleReq = ManifestParser.convertNativeCode(owner, nativeLibraryClauses, false);
+        
+        BundleRequirement ir = findRequirement(nativeBundleReq, NativeNamespace.NATIVE_NAMESPACE);
+        
+        String filterStr = (String)ir.getDirectives().get(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE);
+        
+        Filter actualFilter = FrameworkUtil.createFilter(filterStr);
+        
+        Filter expectedFilter = FrameworkUtil.createFilter("(&(|" + 
+                "(osgi.native.osname~=windows95)(osgi.native.osname~=windows98)(osgi.native.osname~=windowsnt)" +
+                ")" + 
+                "(osgi.native.processor~=x86)" + 
+                "(|(osgi.native.language~=en)" + 
+                "(osgi.native.language~=se)" + 
+                ")"+
+                "(com.acme.windowing=win32))");
+        assertEquals("Filter Should contain native requirements", expectedFilter, actualFilter);
+        
+    }
 
     private BundleCapability findCapability(Collection<BundleCapability> capabilities, String namespace)
     {
@@ -111,4 +154,16 @@
         }
         return null;
     }
+    
+    private BundleRequirement findRequirement(Collection<BundleRequirement> requirements, String namespace)
+    {
+        for(BundleRequirement requirement: requirements)
+        {
+            if(namespace.equals(requirement.getNamespace()))
+            {
+                return requirement;
+            }
+        }
+        return null;
+    }
 }
diff --git a/framework/src/test/java/org/apache/felix/framework/util/manifestparser/R4LibraryClauseTest.java b/framework/src/test/java/org/apache/felix/framework/util/manifestparser/R4LibraryClauseTest.java
index b5effd2..70ee7e8 100644
--- a/framework/src/test/java/org/apache/felix/framework/util/manifestparser/R4LibraryClauseTest.java
+++ b/framework/src/test/java/org/apache/felix/framework/util/manifestparser/R4LibraryClauseTest.java
@@ -41,7 +41,7 @@
         assertEquals("digitalunix", R4LibraryClause.normalizeOSName("digitalunix_blah"));
         assertEquals("hpux", R4LibraryClause.normalizeOSName("HPUX-999"));
         assertEquals("irix", R4LibraryClause.normalizeOSName("Irixxxx"));
-        assertEquals("macos", R4LibraryClause.normalizeOSName("mac OS X"));
+        assertEquals("macosx", R4LibraryClause.normalizeOSName("mac OS X"));
         assertEquals("netware", R4LibraryClause.normalizeOSName("Netware"));
         assertEquals("openbsd", R4LibraryClause.normalizeOSName("OpenBSD-0000"));
         assertEquals("netbsd", R4LibraryClause.normalizeOSName("netbsd "));
@@ -81,4 +81,65 @@
         assertEquals("windowsxp", R4LibraryClause.normalizeOSName("windowsxp"));
         assertEquals("win32", R4LibraryClause.normalizeOSName("win32"));
     }
+    
+    public void testgetOsNameWithAliases() {
+        assertTrue(R4LibraryClause.getOsNameWithAliases("win 32").contains("win32"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Win*").contains("win32"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Windows 95").contains("windows95"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Windows 98").contains("windows98"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("WinNT").contains("windowsnt"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Win2000").contains("windows2000"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Win2003").contains("windows2003"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Windows Server 2008").contains("windowsserver2008"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Windows Server 2012").contains("windowsserver2012"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("WinXP").contains("windowsxp"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("WinCE").contains("windowsce"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("WinVista").contains("windowsvista"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Windows 7").contains("windows7"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Win8").contains("windows8"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Linux1.2.3").contains("linux"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("AIX-4.5.6").contains("aix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("digitalunix_blah").contains("digitalunix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("HPUX-999").contains("hpux"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Irixxxx").contains("irix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("mac OS X").contains("mac os x"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Netware").contains("netware"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("OpenBSD-0000").contains("openbsd"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("netbsd ").contains("netbsd"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("os/2").contains("os2"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("procnto").contains("qnx"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("Solaris 9").contains("solaris"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("SunOS8").contains("sunos"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("VxWorks").contains("vxworks"));
+
+        // Try all the already normalized names
+        assertTrue(R4LibraryClause.getOsNameWithAliases("aix").contains("aix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("digitalunix").contains("digitalunix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("hpux").contains("hpux"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("irix").contains("irix"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("linux").contains("linux"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("mac os").contains("mac os"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("netbsd").contains("netbsd"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("netware").contains("netware"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("openbsd").contains("openbsd"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("os2").contains("os2"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("qnx").contains("qnx"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("solaris").contains("solaris"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("sunos").contains("sunos"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("vxworks").contains("vxworks"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows2000").contains("windows2000"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows2003").contains("windows2003"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows7").contains("windows7"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows8").contains("windows8"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows9").contains("windows9"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows95").contains("windows95"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windows98").contains("windows98"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsce").contains("windowsce"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsnt").contains("windowsnt"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsserver2008").contains("windowsserver2008"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsserver2012").contains("windowsserver2012"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsvista").contains("windowsvista"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("windowsxp").contains("windowsxp"));
+        assertTrue(R4LibraryClause.getOsNameWithAliases("win32").contains("win32"));
+    }
 }