You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2013/04/04 11:43:37 UTC

svn commit: r1464402 [11/11] - in /ace/trunk: org.apache.ace.deployment.api/ org.apache.ace.deployment.deploymentadmin/ org.apache.ace.deployment.itest/ org.apache.ace.deployment.itest/src/org/apache/ace/it/deployment/ org.apache.ace.deployment.provide...

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4Library.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4Library.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4Library.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4Library.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,183 @@
+/*
+ * 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.util.manifestparser;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.osgi.framework.Constants;
+
+public class R4Library
+{
+    private String m_libraryFile;
+    private String[] m_osnames;
+    private String[] m_processors;
+    private String[] m_osversions;
+    private String[] m_languages;
+    private String m_selectionFilter;
+
+    public R4Library(
+        String libraryFile, String[] osnames, String[] processors, String[] osversions,
+        String[] languages, String selectionFilter) throws Exception
+    {
+        m_libraryFile = libraryFile;
+        m_osnames = osnames;
+        m_processors = processors;
+        m_osversions = osversions;
+        m_languages = languages;
+        m_selectionFilter = selectionFilter;
+    }
+
+    public String getEntryName()
+    {
+        return m_libraryFile;
+    }
+
+    public String[] getOSNames()
+    {
+        return m_osnames;
+    }
+
+    public String[] getProcessors()
+    {
+        return m_processors;
+    }
+
+    public String[] getOSVersions()
+    {
+        return m_osversions;
+    }
+
+    public String[] getLanguages()
+    {
+        return m_languages;
+    }
+
+    public String getSelectionFilter()
+    {
+        return m_selectionFilter;
+    }
+
+    /**
+     * <p>
+     * Determines if the specified native library name matches this native
+     * library definition.
+     * </p>
+     * @param name the native library name to try to match.
+     * @return <tt>true</tt> if this native library name matches this native
+     *         library definition; <tt>false</tt> otherwise.
+    **/
+    public boolean match(Map configMap, String name)
+    {
+        // First, check for an exact match.
+        boolean matched = false;
+        if (m_libraryFile.equals(name) || m_libraryFile.endsWith("/" + name))
+        {
+            matched = true;
+        }
+
+        // Then check the mapped name.
+        String libname = System.mapLibraryName(name);
+        // As well as any additional library file extensions.
+        List<String> exts = ManifestParser.parseDelimitedString(
+            (String) configMap.get(Constants.FRAMEWORK_LIBRARY_EXTENSIONS), ",");
+        if (exts == null)
+        {
+            exts = new ArrayList<String>();
+        }
+        // For Mac OSX, try dylib too.
+        if (libname.endsWith(".jnilib") && m_libraryFile.endsWith(".dylib"))
+        {
+            exts.add("dylib");
+        }
+        // Loop until we find a match or not.
+        int extIdx = -1;
+        while (!matched && (extIdx < exts.size()))
+        {
+            // Check if the current name matches.
+            if (m_libraryFile.equals(libname) || m_libraryFile.endsWith("/" + libname))
+            {
+                matched = true;
+            }
+
+            // Increment extension index.
+            extIdx++;
+
+            // If we have other native library extensions to try, then
+            // calculate the new native library name.
+            if (!matched && (extIdx < exts.size()))
+            {
+                int idx = libname.lastIndexOf(".");
+                libname = (idx < 0)
+                    ? libname + "." + exts.get(extIdx)
+                    : libname.substring(0, idx + 1) + exts.get(extIdx);
+            }
+        }
+
+        return matched;
+    }
+
+    public String toString()
+    {
+        if (m_libraryFile != null)
+        {
+            StringBuffer sb = new StringBuffer();
+            sb.append(m_libraryFile);
+            for (int i = 0; (m_osnames != null) && (i < m_osnames.length); i++)
+            {
+                sb.append(';');
+                sb.append(Constants.BUNDLE_NATIVECODE_OSNAME);
+                sb.append('=');
+                sb.append(m_osnames[i]);
+            }
+            for (int i = 0; (m_processors != null) && (i < m_processors.length); i++)
+            {
+                sb.append(';');
+                sb.append(Constants.BUNDLE_NATIVECODE_PROCESSOR);
+                sb.append('=');
+                sb.append(m_processors[i]);
+            }
+            for (int i = 0; (m_osversions != null) && (i < m_osversions.length); i++)
+            {
+                sb.append(';');
+                sb.append(Constants.BUNDLE_NATIVECODE_OSVERSION);
+                sb.append('=');
+                sb.append(m_osversions[i]);
+            }
+            for (int i = 0; (m_languages != null) && (i < m_languages.length); i++)
+            {
+                sb.append(';');
+                sb.append(Constants.BUNDLE_NATIVECODE_LANGUAGE);
+                sb.append('=');
+                sb.append(m_languages[i]);
+            }
+            if (m_selectionFilter != null)
+            {
+                sb.append(';');
+                sb.append(Constants.SELECTION_FILTER_ATTRIBUTE);
+                sb.append('=');
+                sb.append('\'');
+                sb.append(m_selectionFilter);
+            }
+
+            return sb.toString();
+        }
+        return "*";
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,523 @@
+/*
+ * 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.util.manifestparser;
+
+import java.util.*;
+
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.VersionRange;
+import org.osgi.framework.*;
+
+public class R4LibraryClause
+{
+    private final String[] m_libraryEntries;
+    private final String[] m_osnames;
+    private final String[] m_processors;
+    private final String[] m_osversions;
+    private final String[] m_languages;
+    private final String m_selectionFilter;
+
+    public R4LibraryClause(String[] libraryEntries, String[] osnames,
+        String[] processors, String[] osversions, String[] languages,
+        String selectionFilter)
+    {
+        m_libraryEntries = libraryEntries;
+        m_osnames = osnames;
+        m_processors = processors;
+        m_osversions = osversions;
+        m_languages = languages;
+        m_selectionFilter = selectionFilter;
+    }
+
+    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;
+    }
+
+    public String[] getLibraryEntries()
+    {
+        return m_libraryEntries;
+    }
+
+    public String[] getOSNames()
+    {
+        return m_osnames;
+    }
+
+    public String[] getProcessors()
+    {
+        return m_processors;
+    }
+
+    public String[] getOSVersions()
+    {
+        return m_osversions;
+    }
+
+    public String[] getLanguages()
+    {
+        return m_languages;
+    }
+
+    public String getSelectionFilter()
+    {
+        return m_selectionFilter;
+    }
+
+    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);
+
+        // Check library's osname.
+        if (!checkOSNames(normal_osname, getOSNames()))
+        {
+            return false;
+        }
+
+        // Check library's processor.
+        if (!checkProcessors(normal_processor, getProcessors()))
+        {
+            return false;
+        }
+
+        // Check library's osversion if specified.
+        if ((getOSVersions() != null) &&
+            (getOSVersions().length > 0) &&
+            !checkOSVersions(normal_osversion, getOSVersions()))
+        {
+            return false;
+        }
+
+        // Check library's language if specified.
+        if ((getLanguages() != null) &&
+            (getLanguages().length > 0) &&
+            !checkLanguages(normal_language, getLanguages()))
+        {
+            return false;
+        }
+
+        // Check library's selection-filter if specified.
+        if ((getSelectionFilter() != null) &&
+            (getSelectionFilter().length() >= 0) &&
+            !checkSelectionFilter(configMap, getSelectionFilter()))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean checkOSNames(String currentOSName, String[] osnames)
+    {
+        boolean win32 = currentOSName.startsWith("win") &&
+            (currentOSName.equals("windows95")
+            || currentOSName.equals("windows98")
+            || currentOSName.equals("windowsnt")
+            || currentOSName.equals("windows2000")
+            || currentOSName.equals("windows2003")
+            || currentOSName.equals("windowsxp")
+            || currentOSName.equals("windowsce")
+            || currentOSName.equals("windowsvista")
+            || currentOSName.equals("windows7"));
+
+        for (int i = 0; (osnames != null) && (i < osnames.length); i++)
+        {
+            if (osnames[i].equals(currentOSName) ||
+                ("win32".equals(osnames[i]) && win32))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkProcessors(String currentProcessor, String[] processors)
+    {
+        for (int i = 0; (processors != null) && (i < processors.length); i++)
+        {
+            if (processors[i].equals(currentProcessor))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkOSVersions(String currentOSVersion, String[] osversions)
+        throws BundleException
+    {
+        for (int i = 0; (osversions != null) && (i < osversions.length); i++)
+        {
+            try
+            {
+                VersionRange range = VersionRange.parse(osversions[i]);
+                if (range.isInRange(new Version(currentOSVersion)))
+                {
+                    return true;
+                }
+            }
+            catch (Exception ex)
+            {
+                throw new BundleException(
+                    "Error evaluating osversion: " + osversions[i], ex);
+            }
+        }
+        return false;
+    }
+
+    private boolean checkLanguages(String currentLanguage, String[] languages)
+    {
+        for (int i = 0; (languages != null) && (i < languages.length); i++)
+        {
+            if (languages[i].equals(currentLanguage))
+            {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean checkSelectionFilter(Map configMap, String expr)
+        throws BundleException
+    {
+        // Get all framework properties
+        Dictionary dict = new Hashtable();
+        for (Iterator i = configMap.keySet().iterator(); i.hasNext(); )
+        {
+            Object key = i.next();
+            dict.put(key, configMap.get(key));
+        }
+        // Compute expression
+        try
+        {
+            Filter filter = FrameworkUtil.createFilter(expr);
+            return filter.match(dict);
+        }
+        catch (Exception ex)
+        {
+            throw new BundleException(
+                "Error evaluating filter expression: " + expr, ex);
+        }
+    }
+
+    public static R4LibraryClause parse(Logger logger, String s)
+    {
+        try
+        {
+            if ((s == null) || (s.length() == 0))
+            {
+                return null;
+            }
+
+            if (s.equals(FelixConstants.BUNDLE_NATIVECODE_OPTIONAL))
+            {
+                return new R4LibraryClause(null, null, null, null, null, null);
+            }
+
+            // The tokens are separated by semicolons and may include
+            // any number of libraries along with one set of associated
+            // properties.
+            StringTokenizer st = new StringTokenizer(s, ";");
+            String[] libEntries = new String[st.countTokens()];
+            List osNameList = new ArrayList();
+            List osVersionList = new ArrayList();
+            List processorList = new ArrayList();
+            List languageList = new ArrayList();
+            String selectionFilter = null;
+            int libCount = 0;
+            while (st.hasMoreTokens())
+            {
+                String token = st.nextToken().trim();
+                if (token.indexOf('=') < 0)
+                {
+                    // Remove the slash, if necessary.
+                    libEntries[libCount] = (token.charAt(0) == '/')
+                        ? token.substring(1)
+                        : token;
+                    libCount++;
+                }
+                else
+                {
+                    // Check for valid native library properties; defined as
+                    // a property name, an equal sign, and a value.
+                    // NOTE: StringTokenizer can not be used here because
+                    // a value can contain one or more "=" too, e.g.,
+                    // selection-filter="(org.osgi.framework.windowing.system=gtk)"
+                    String property = null;
+                    String value = null;
+                    if (!(token.indexOf("=") > 1))
+                    {
+                        throw new IllegalArgumentException(
+                            "Bundle manifest native library entry malformed: " + token);
+                    }
+                    else
+                    {
+                        property = (token.substring(0, token.indexOf("=")))
+                            .trim().toLowerCase();
+                        value = (token.substring(token.indexOf("=") + 1, token
+                            .length())).trim();
+                    }
+
+                    // Values may be quoted, so remove quotes if present.
+                    if (value.charAt(0) == '"')
+                    {
+                        // This should always be true, otherwise the
+                        // value wouldn't be properly quoted, but we
+                        // will check for safety.
+                        if (value.charAt(value.length() - 1) == '"')
+                        {
+                            value = value.substring(1, value.length() - 1);
+                        }
+                        else
+                        {
+                            value = value.substring(1);
+                        }
+                    }
+                    // Add the value to its corresponding property list.
+                    if (property.equals(Constants.BUNDLE_NATIVECODE_OSNAME))
+                    {
+                        osNameList.add(normalizeOSName(value));
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_OSVERSION))
+                    {
+                        osVersionList.add(normalizeOSVersion(value));
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_PROCESSOR))
+                    {
+                        processorList.add(normalizeProcessor(value));
+                    }
+                    else if (property.equals(Constants.BUNDLE_NATIVECODE_LANGUAGE))
+                    {
+                        languageList.add(value);
+                    }
+                    else if (property.equals(Constants.SELECTION_FILTER_ATTRIBUTE))
+                    {
+// TODO: NATIVE - I believe we can have multiple selection filters too.
+                        selectionFilter = value;
+                    }
+                }
+            }
+
+            if (libCount == 0)
+            {
+                return null;
+            }
+
+            // Shrink lib file array.
+            String[] actualLibEntries = new String[libCount];
+            System.arraycopy(libEntries, 0, actualLibEntries, 0, libCount);
+            return new R4LibraryClause(
+                actualLibEntries,
+                (String[]) osNameList.toArray(new String[osNameList.size()]),
+                (String[]) processorList.toArray(new String[processorList.size()]),
+                (String[]) osVersionList.toArray(new String[osVersionList.size()]),
+                (String[]) languageList.toArray(new String[languageList.size()]),
+                selectionFilter);
+        }
+        catch (RuntimeException ex)
+        {
+            logger.log(Logger.LOG_ERROR,
+                "Error parsing native library header.", ex);
+            throw ex;
+        }
+    }
+
+    public static String normalizeOSName(String value)
+    {
+        value = value.toLowerCase();
+
+        if (value.startsWith("win"))
+        {
+            String os = "win";
+            if (value.indexOf("32") >= 0 || value.indexOf("*") >= 0)
+            {
+                os = "win32";
+            }
+            else if (value.indexOf("95") >= 0)
+            {
+                os = "windows95";
+            }
+            else if (value.indexOf("98") >= 0)
+            {
+                os = "windows98";
+            }
+            else if (value.indexOf("nt") >= 0)
+            {
+                os = "windowsnt";
+            }
+            else if (value.indexOf("2000") >= 0)
+            {
+                os = "windows2000";
+            }
+            else if (value.indexOf("2003") >= 0)
+            {
+                os = "windows2003";
+            }
+            else if (value.indexOf("xp") >= 0)
+            {
+                os = "windowsxp";
+            }
+            else if (value.indexOf("ce") >= 0)
+            {
+                os = "windowsce";
+            }
+            else if (value.indexOf("vista") >= 0)
+            {
+                os = "windowsvista";
+            }
+            // will need better test here if any future Windows version has a 7 in it!
+            else if (value.indexOf("7") >= 0)
+            {
+                os = "windows7";
+            }
+            return os;
+        }
+        else if (value.startsWith("linux"))
+        {
+            return "linux";
+        }
+        else if (value.startsWith("aix"))
+        {
+            return "aix";
+        }
+        else if (value.startsWith("digitalunix"))
+        {
+            return "digitalunix";
+        }
+        else if (value.startsWith("hpux"))
+        {
+            return "hpux";
+        }
+        else if (value.startsWith("irix"))
+        {
+            return "irix";
+        }
+        else if (value.startsWith("macos") || value.startsWith("mac os"))
+        {
+            return "macos";
+        }
+        else if (value.startsWith("netware"))
+        {
+            return "netware";
+        }
+        else if (value.startsWith("openbsd"))
+        {
+            return "openbsd";
+        }
+        else if (value.startsWith("netbsd"))
+        {
+            return "netbsd";
+        }
+        else if (value.startsWith("os2") || value.startsWith("os/2"))
+        {
+            return "os2";
+        }
+        else if (value.startsWith("qnx") || value.startsWith("procnto"))
+        {
+            return "qnx";
+        }
+        else if (value.startsWith("solaris"))
+        {
+            return "solaris";
+        }
+        else if (value.startsWith("sunos"))
+        {
+            return "sunos";
+        }
+        else if (value.startsWith("vxworks"))
+        {
+            return "vxworks";
+        }
+        return value;
+    }
+
+    public static String normalizeProcessor(String value)
+    {
+        value = value.toLowerCase();
+
+        if (value.startsWith("x86-64") || value.startsWith("amd64") || 
+            value.startsWith("em64") || value.startsWith("x86_64"))
+        {
+            return "x86-64";
+        }
+        else if (value.startsWith("x86") || value.startsWith("pentium")
+            || value.startsWith("i386") || value.startsWith("i486")
+            || value.startsWith("i586") || value.startsWith("i686"))
+        {
+            return "x86";
+        }
+        else if (value.startsWith("68k"))
+        {
+            return "68k";
+        }
+        else if (value.startsWith("arm"))
+        {
+            return "arm";
+        }
+        else if (value.startsWith("alpha"))
+        {
+            return "alpha";
+        }
+        else if (value.startsWith("ignite") || value.startsWith("psc1k"))
+        {
+            return "ignite";
+        }
+        else if (value.startsWith("mips"))
+        {
+            return "mips";
+        }
+        else if (value.startsWith("parisc"))
+        {
+            return "parisc";
+        }
+        else if (value.startsWith("powerpc") || value.startsWith("power")
+            || value.startsWith("ppc"))
+        {
+            return "powerpc";
+        }
+        else if (value.startsWith("sparc"))
+        {
+            return "sparc";
+        }
+        return value;
+    }
+
+    public static String normalizeOSVersion(String value)
+    {
+        // Header: 'Bundle-NativeCode', Parameter: 'osversion'
+        // Standardized 'osversion': major.minor.micro, only digits
+        try
+        {
+            return VersionRange.parse(value).toString();
+        }
+        catch (Exception ex)
+        {
+            return Version.emptyVersion.toString();
+        }
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleCapabilityImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleCapabilityImpl.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleCapabilityImpl.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleCapabilityImpl.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,200 @@
+/*
+ * 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.wiring;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Collections;
+import java.util.Set;
+import java.util.Map;
+import java.util.List;
+import java.util.StringTokenizer;
+import org.apache.felix.framework.capabilityset.SimpleFilter;
+import org.apache.felix.framework.util.Util;
+import org.apache.felix.framework.util.manifestparser.ManifestParser;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class BundleCapabilityImpl implements BundleCapability
+{
+    public static final String SINGLETON_NAMESPACE = "singleton";
+
+    public static final String VERSION_ATTR = "version";
+
+    private final BundleRevision m_revision;
+    private final String m_namespace;
+    private final Map<String, String> m_dirs;
+    private final Map<String, Object> m_attrs;
+    private final List<String> m_uses;
+    private final List<List<String>> m_includeFilter;
+    private final List<List<String>> m_excludeFilter;
+    private final Set<String> m_mandatory;
+
+    public BundleCapabilityImpl(BundleRevision revision, String namespace,
+        Map<String, String> dirs, Map<String, Object> attrs)
+    {
+        m_namespace = namespace;
+        m_revision = revision;
+        m_dirs = Collections.unmodifiableMap(dirs);
+        m_attrs = Collections.unmodifiableMap(attrs);
+
+        // Find all export directives: uses, mandatory, include, and exclude.
+
+        List<String> uses = Collections.EMPTY_LIST;
+        String value = m_dirs.get(Constants.USES_DIRECTIVE);
+        if (value != null)
+        {
+            // Parse these uses directive.
+            StringTokenizer tok = new StringTokenizer(value, ",");
+            uses = new ArrayList(tok.countTokens());
+            while (tok.hasMoreTokens())
+            {
+                uses.add(tok.nextToken().trim());
+            }
+        }
+        m_uses = uses;
+
+        value = m_dirs.get(Constants.INCLUDE_DIRECTIVE);
+        if (value != null)
+        {
+            List<String> filters = ManifestParser.parseDelimitedString(value, ",");
+            m_includeFilter = new ArrayList<List<String>>(filters.size());
+            for (int filterIdx = 0; filterIdx < filters.size(); filterIdx++)
+            {
+                List<String> substrings = SimpleFilter.parseSubstring(filters.get(filterIdx));
+                m_includeFilter.add(substrings);
+            }
+        }
+        else
+        {
+            m_includeFilter = null;
+        }
+
+        value = m_dirs.get(Constants.EXCLUDE_DIRECTIVE);
+        if (value != null)
+        {
+            List<String> filters = ManifestParser.parseDelimitedString(value, ",");
+            m_excludeFilter = new ArrayList<List<String>>(filters.size());
+            for (int filterIdx = 0; filterIdx < filters.size(); filterIdx++)
+            {
+                List<String> substrings = SimpleFilter.parseSubstring(filters.get(filterIdx));
+                m_excludeFilter.add(substrings);
+            }
+        }
+        else
+        {
+            m_excludeFilter = null;
+        }
+
+        Set<String> mandatory = Collections.EMPTY_SET;
+        value = m_dirs.get(Constants.MANDATORY_DIRECTIVE);
+        if (value != null)
+        {
+            List<String> names = ManifestParser.parseDelimitedString(value, ",");
+            mandatory = new HashSet<String>(names.size());
+            for (String name : names)
+            {
+                // If attribute exists, then record it as mandatory.
+                if (m_attrs.containsKey(name))
+                {
+                    mandatory.add(name);
+                }
+                // Otherwise, report an error.
+                else
+                {
+                    throw new IllegalArgumentException(
+                        "Mandatory attribute '" + name + "' does not exist.");
+                }
+            }
+        }
+        m_mandatory = mandatory;
+    }
+
+    public BundleRevision getRevision()
+    {
+        return m_revision;
+    }
+
+    public String getNamespace()
+    {
+        return m_namespace;
+    }
+
+    public Map<String, String> getDirectives()
+    {
+        return m_dirs;
+    }
+
+    public Map<String, Object> getAttributes()
+    {
+        return m_attrs;
+    }
+
+    public boolean isAttributeMandatory(String name)
+    {
+        return !m_mandatory.isEmpty() && m_mandatory.contains(name);
+    }
+
+    public List<String> getUses()
+    {
+        return m_uses;
+    }
+
+    public boolean isIncluded(String name)
+    {
+        if ((m_includeFilter == null) && (m_excludeFilter == null))
+        {
+            return true;
+        }
+
+        // Get the class name portion of the target class.
+        String className = Util.getClassName(name);
+
+        // If there are no include filters then all classes are included
+        // by default, otherwise try to find one match.
+        boolean included = (m_includeFilter == null);
+        for (int i = 0;
+            (!included) && (m_includeFilter != null) && (i < m_includeFilter.size());
+            i++)
+        {
+            included = SimpleFilter.compareSubstring(m_includeFilter.get(i), className);
+        }
+
+        // If there are no exclude filters then no classes are excluded
+        // by default, otherwise try to find one match.
+        boolean excluded = false;
+        for (int i = 0;
+            (!excluded) && (m_excludeFilter != null) && (i < m_excludeFilter.size());
+            i++)
+        {
+            excluded = SimpleFilter.compareSubstring(m_excludeFilter.get(i), className);
+        }
+        return included && !excluded;
+    }
+
+    public String toString()
+    {
+        if (m_revision == null)
+        {
+            return m_attrs.toString();
+        }
+        return "[" + m_revision + "] " + m_namespace + "; " + m_attrs;
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleRequirementImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleRequirementImpl.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleRequirementImpl.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleRequirementImpl.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,109 @@
+/*
+ * 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.wiring;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.apache.felix.framework.capabilityset.CapabilitySet;
+import org.apache.felix.framework.capabilityset.SimpleFilter;
+import org.apache.felix.framework.util.VersionRange;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class BundleRequirementImpl implements BundleRequirement
+{
+    private final BundleRevision m_revision;
+    private final String m_namespace;
+    private final SimpleFilter m_filter;
+    private final boolean m_optional;
+    private final Map<String, String> m_dirs;
+    private final Map<String, Object> m_attrs;
+
+    public BundleRequirementImpl(
+        BundleRevision revision, String namespace,
+        Map<String, String> dirs, Map<String, Object> attrs, SimpleFilter filter)
+    {
+        m_revision = revision;
+        m_namespace = namespace;
+        m_dirs = Collections.unmodifiableMap(dirs);
+        m_attrs = Collections.unmodifiableMap(attrs);
+        m_filter = filter;
+
+        // Find resolution import directives.
+        boolean optional = false;
+        if (m_dirs.containsKey(Constants.RESOLUTION_DIRECTIVE)
+            && m_dirs.get(Constants.RESOLUTION_DIRECTIVE).equals(Constants.RESOLUTION_OPTIONAL))
+        {
+            optional = true;
+        }
+        m_optional = optional;
+    }
+
+    public BundleRequirementImpl(
+        BundleRevision revision, String namespace,
+        Map<String, String> dirs, Map<String, Object> attrs)
+    {
+        this(revision, namespace, dirs, Collections.EMPTY_MAP, SimpleFilter.convert(attrs));
+    }
+
+    public String getNamespace()
+    {
+        return m_namespace;
+    }
+
+    public Map<String, String> getDirectives()
+    {
+        return m_dirs;
+    }
+
+    public Map<String, Object> getAttributes()
+    {
+        return m_attrs;
+    }
+
+    public BundleRevision getRevision()
+    {
+        return m_revision;
+    }
+
+    public boolean matches(BundleCapability cap)
+    {
+        return CapabilitySet.matches((BundleCapabilityImpl) cap, getFilter());
+    }
+
+    public boolean isOptional()
+    {
+        return m_optional;
+    }
+
+    public SimpleFilter getFilter()
+    {
+        return m_filter;
+    }
+
+    public String toString()
+    {
+        return "[" + m_revision + "] " + m_namespace + "; " + getFilter().toString();
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleWireImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleWireImpl.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleWireImpl.java (added)
+++ ace/trunk/org.apache.ace.verifier/src/org/apache/felix/framework/wiring/BundleWireImpl.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,79 @@
+/*
+ * 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.wiring;
+
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+
+public class BundleWireImpl implements BundleWire
+{
+    private final BundleRevision m_requirer;
+    private final BundleRequirement m_req;
+    private final BundleRevision m_provider;
+    private final BundleCapability m_cap;
+
+    public BundleWireImpl(BundleRevision requirer, BundleRequirement req,
+        BundleRevision provider, BundleCapability cap)
+    {
+        m_requirer = requirer;
+        m_req = req;
+        m_provider = provider;
+        m_cap = cap;
+    }
+
+    public BundleRevision getRequirer()
+    {
+        return m_requirer;
+    }
+
+    public BundleWiring getRequirerWiring()
+    {
+        return m_requirer.getWiring();
+    }
+
+    public BundleRequirement getRequirement()
+    {
+        return m_req;
+    }
+
+    public BundleRevision getProvider()
+    {
+        return m_provider;
+    }
+
+    public BundleWiring getProviderWiring()
+    {
+        return m_provider.getWiring();
+    }
+
+    public BundleCapability getCapability()
+    {
+        return m_cap;
+    }
+
+    public String toString()
+    {
+        return m_req
+            + " -> "
+            + "[" + m_provider + "]";
+    }
+}
\ No newline at end of file

Added: ace/trunk/org.apache.ace.verifier/test/org/apache/ace/deployment/verifier/impl/VerifierTest.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/test/org/apache/ace/deployment/verifier/impl/VerifierTest.java?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/test/org/apache/ace/deployment/verifier/impl/VerifierTest.java (added)
+++ ace/trunk/org.apache.ace.verifier/test/org/apache/ace/deployment/verifier/impl/VerifierTest.java Thu Apr  4 09:43:34 2013
@@ -0,0 +1,131 @@
+package org.apache.ace.deployment.verifier.impl;
+
+import org.testng.annotations.Test;
+import org.testng.AssertJUnit;
+import static org.apache.ace.test.utils.TestUtils.UNIT;
+import static org.testng.Assert.*;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.ace.deployment.verifier.VerifierService;
+import org.apache.ace.deployment.verifier.VerifierService.VerifyEnvironment;
+import org.apache.ace.deployment.verifier.VerifierService.VerifyReporter;
+import org.apache.felix.framework.util.FelixConstants;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.service.log.LogEntry;
+
+public class VerifierTest {
+    @Test(groups = { UNIT })
+	public void testResolve() throws BundleException {
+		VerifierService verifier = new VerifierServiceImpl();
+		VerifyEnvironment env = verifier.createEnvironment(new HashMap<String, String>() {
+			{
+				put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, VerifierService.EE_1_6);
+				put(Constants.FRAMEWORK_OS_NAME, "macosx");
+				put(Constants.FRAMEWORK_OS_VERSION, "10.5");
+			}
+		}, new VerifyReporter() {
+			
+			public void reportWire(BundleRevision importer,
+					BundleRequirement reqirement, BundleRevision exporter,
+					BundleCapability capability) {
+				System.out.println("WIRE: " + importer + " - " + reqirement + " - " + capability + " -> " + exporter);
+			}
+			
+			public void reportLog(LogEntry logEntry) {
+				System.out.println("Log(" + logEntry.getTime() + "): " + logEntry.getLevel() + " " + logEntry.getMessage());
+				if (logEntry.getException() != null) {
+					logEntry.getException().printStackTrace();
+				}
+			}
+			
+			public void reportException(Exception ex) {
+				ex.printStackTrace();
+			}
+		});
+		Set<BundleRevision> bundles = new HashSet<BundleRevision>();
+		bundles.add(env.addBundle(0, new HashMap<String, String>(){
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+				put(Constants.EXPORT_PACKAGE, VerifierService.SYSTEM_PACKAGES + "," + VerifierService.JRE_1_6_PACKAGES);
+			}
+		}));
+		bundles.add(env.addBundle(1, new HashMap<String, String>() {
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, "org.test.foo");
+				put(Constants.IMPORT_PACKAGE, "org.foo, org.osgi.framework");
+			}
+		}));
+		bundles.add(env.addBundle(2, new HashMap<String, String>() {
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, "org.test.foo2");
+				put(Constants.EXPORT_PACKAGE, "org.foo" +
+						"");
+			}
+		}));
+		AssertJUnit.assertTrue(" Unable to resolve resolvable state.", env.verifyResolve(bundles, null, null));
+	}
+	
+    @Test(groups = { UNIT })
+	public void testResolveFail() throws BundleException {
+		VerifierService verifier = new VerifierServiceImpl();
+		VerifyEnvironment env = verifier.createEnvironment(new HashMap<String, String>(){
+			{
+				put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, VerifierService.EE_1_6);
+				put(Constants.FRAMEWORK_OS_NAME, "macosx");
+				put(Constants.FRAMEWORK_OS_VERSION, "10.5");
+			}
+		}, new VerifyReporter() {
+			
+			public void reportWire(BundleRevision importer,
+					BundleRequirement reqirement, BundleRevision exporter,
+					BundleCapability capability) {
+				System.out.println("WIRE: " + importer + " - " + reqirement + " - " + capability + " -> " + exporter);
+			}
+			
+			public void reportLog(LogEntry logEntry) {
+				System.out.println("Log(" + logEntry.getTime() + "): " + logEntry.getLevel() + " " + logEntry.getMessage());
+				if (logEntry.getException() != null) {
+					logEntry.getException().printStackTrace();
+				}
+			}
+			
+			public void reportException(Exception ex) {
+				ex.printStackTrace();
+			}
+		});
+		Set<BundleRevision> bundles = new HashSet<BundleRevision>();
+		bundles.add(env.addBundle(0, new HashMap<String, String>(){
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+				put(Constants.EXPORT_PACKAGE, VerifierService.SYSTEM_PACKAGES + "," + VerifierService.JRE_1_6_PACKAGES);
+			}
+		}));
+		bundles.add(env.addBundle(1, new HashMap<String, String>() {
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, "org.test.foo");
+				put(Constants.IMPORT_PACKAGE, "org.foo");
+			}
+		}));
+		bundles.add(env.addBundle(2, new HashMap<String, String>() {
+			{
+				put(Constants.BUNDLE_MANIFESTVERSION, "2");
+				put(Constants.BUNDLE_SYMBOLICNAME, "org.test.foo2");
+				put(Constants.EXPORT_PACKAGE, "org.foo2" +
+						"");
+			}
+		}));
+		AssertJUnit.assertFalse("Resolving unresolvable", env.verifyResolve(bundles, null, null));
+	}
+}

Added: ace/trunk/org.apache.ace.verifier/ui.bnd
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.verifier/ui.bnd?rev=1464402&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.verifier/ui.bnd (added)
+++ ace/trunk/org.apache.ace.verifier/ui.bnd Thu Apr  4 09:43:34 2013
@@ -0,0 +1,5 @@
+Private-Package: org.apache.ace.deployment.verifier.ui
+Bundle-Activator: org.apache.ace.deployment.verifier.ui.Activator
+Import-Package: org.osgi.framework;version='[1.5,2)',\
+	*
+Bundle-Version: 1.0.0