felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From rickh...@apache.org
Subject svn commit: r807795 [1/5] - in /felix/sandbox/rickhall/resolver: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/felix/ src/main/java/org/apache/felix/resolver/ src/main/java/org/apache/felix/resol...
Date Tue, 25 Aug 2009 20:30:34 GMT
Author: rickhall
Date: Tue Aug 25 20:30:33 2009
New Revision: 807795

URL: http://svn.apache.org/viewvc?rev=807795&view=rev
Log:
Experimenting with the resolver.

Added:
    felix/sandbox/rickhall/resolver/
    felix/sandbox/rickhall/resolver/pom.xml
    felix/sandbox/rickhall/resolver/src/
    felix/sandbox/rickhall/resolver/src/main/
    felix/sandbox/rickhall/resolver/src/main/java/
    felix/sandbox/rickhall/resolver/src/main/java/org/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Attribute.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ExportedPackage.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ImportedPackage.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Main.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Module.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolveException.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Resolver.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolverConflictException.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Version.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/VersionRange.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Wire.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/CandidateSet.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolver.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolverImpl.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/PackageSource.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/ResolvedPackage.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/Capability.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/Constants.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/Main.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/ManifestParser.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/R4Attribute.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/R4Directive.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/R4Library.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/R4LibraryClause.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/Requirement.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/SourceMain.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/StringMap.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/manifestparser/Util.java
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/
    felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/prototype/ProtoResolver.java

Added: felix/sandbox/rickhall/resolver/pom.xml
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/pom.xml?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/pom.xml (added)
+++ felix/sandbox/rickhall/resolver/pom.xml Tue Aug 25 20:30:33 2009
@@ -0,0 +1,47 @@
+<!-- 
+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. 
+-->
+<project>
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>jar</packaging>
+  <name>Apache Felix Prototype Resolver</name>
+  <groupId>org.apache.felix</groupId>
+  <artifactId>org.apache.felix.resolver</artifactId>
+  <version>0.1.0-SNAPSHOT</version>
+  <dependencies>
+  </dependencies>
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.5</source>
+          <target>1.5</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-resources-plugin</artifactId>
+        <configuration>
+          <encoding>UTF-8</encoding>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Attribute.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Attribute.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Attribute.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Attribute.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,53 @@
+/*
+ *  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.resolver;
+
+public class Attribute
+{
+    private final String m_name;
+    private final Object m_value;
+    private final boolean m_isMandatory;
+
+    public Attribute(String name, Object value, boolean isMandatory)
+    {
+        m_name = name;
+        m_value = value;
+        m_isMandatory = isMandatory;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public Object getValue()
+    {
+        return m_value;
+    }
+
+    public boolean isMandatory()
+    {
+        return m_isMandatory;
+    }
+
+    public String toString()
+    {
+        return m_name + "=" + m_value;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ExportedPackage.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ExportedPackage.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ExportedPackage.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ExportedPackage.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,132 @@
+/*
+ *  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.resolver;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.StringTokenizer;
+import org.apache.felix.resolver.manifestparser.Constants;
+
+public class ExportedPackage
+{
+    private final String m_name;
+    private final List m_uses;
+    private final Map<String, Attribute> m_attrs;
+
+    public ExportedPackage(String name)
+    {
+        m_name = name;
+        m_uses = new ArrayList<String>();
+        m_attrs = new HashMap<String, Attribute>();
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public ExportedPackage using(String uses)
+    {
+        StringTokenizer st = new StringTokenizer(uses, ",");
+        while (st.hasMoreTokens())
+        {
+            m_uses.add(st.nextToken().trim());
+        }
+        return this;
+    }
+
+    public ExportedPackage with(String attr)
+    {
+        int idx = attr.indexOf('=');
+        if (idx > 0)
+        {
+            String n = attr.substring(0, idx);
+            String v = attr.substring(idx + 1);
+            if (n.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE)
+                || n.equalsIgnoreCase(Constants.BUNDLE_VERSION_ATTRIBUTE))
+            {
+                m_attrs.put(n, new Attribute(n, Version.parseVersion(v), false));
+            }
+            else
+            {
+                m_attrs.put(n, new Attribute(n, v, false));
+            }
+        }
+        return this;
+    }
+
+    public ExportedPackage withMandatory(String attr)
+    {
+        int idx = attr.indexOf('=');
+        if (idx > 0)
+        {
+            String n = attr.substring(0, idx);
+            String v = attr.substring(idx + 1);
+            if (n.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE)
+                || n.equalsIgnoreCase(Constants.BUNDLE_VERSION_ATTRIBUTE))
+            {
+                m_attrs.put(n, new Attribute(n, Version.parseVersion(v), true));
+            }
+            else
+            {
+                m_attrs.put(n, new Attribute(n, v, true));
+            }
+        }
+        return this;
+    }
+
+    public Attribute getAttribute(String name)
+    {
+        return m_attrs.get(name);
+    }
+
+    public boolean satisfies(ImportedPackage ip)
+    {
+        boolean result = true;
+
+        // Check mandatory export attributes.
+        for (Iterator<Entry<String, Attribute>> it = m_attrs.entrySet().iterator(); it.hasNext(); )
+        {
+            Attribute attr = it.next().getValue();
+            if (attr.isMandatory() &&
+                ((ip.getAttribute(attr.getName()) == null)
+                || !ip.getAttribute(attr.getName()).getValue().equals(attr.getValue())))
+            {
+                result = false;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    public List<String> getUses()
+    {
+        return m_uses;
+    }
+
+    public String toString()
+    {
+        return "export " + m_name;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ImportedPackage.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ImportedPackage.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ImportedPackage.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ImportedPackage.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,140 @@
+/*
+ *  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.resolver;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.apache.felix.resolver.manifestparser.Constants;
+
+public class ImportedPackage
+{
+    private final String m_name;
+    private final Map<String, Attribute> m_attrs;
+    private boolean m_optional = false;
+
+    public ImportedPackage(String name)
+    {
+        m_name = name;
+        m_attrs = new HashMap<String, Attribute>();
+    }
+
+    public ImportedPackage optional()
+    {
+        m_optional = true;
+        return this;
+    }
+
+    public ImportedPackage with(String attr)
+    {
+        int idx = attr.indexOf('=');
+        if (idx > 0)
+        {
+            String n = attr.substring(0, idx);
+            String v = attr.substring(idx + 1);
+            if (n.equalsIgnoreCase(Constants.VERSION_ATTRIBUTE)
+                || n.equalsIgnoreCase(Constants.BUNDLE_VERSION_ATTRIBUTE))
+            {
+                m_attrs.put(n, new Attribute(n, VersionRange.parse(v), false));
+            }
+            else
+            {
+                m_attrs.put(n, new Attribute(n, v, false));
+            }
+        }
+        return this;
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public Attribute getAttribute(String name)
+    {
+        return m_attrs.get(name);
+    }
+
+    public boolean isSatistfiedBy(ExportedPackage ep)
+    {
+        boolean result = m_name.equals(ep.getName());
+
+        // Check specified import attributes.
+        if (result)
+        {
+            for (Iterator<Entry<String, Attribute>> it = m_attrs.entrySet().iterator(); it.hasNext(); )
+            {
+                Attribute attr = it.next().getValue();
+                Attribute epAttr = ep.getAttribute(attr.getName());
+                if (epAttr != null)
+                {
+                    if (epAttr.getValue() instanceof Version)
+                    {
+                        result = ((VersionRange) attr.getValue()).isInRange((Version) epAttr.getValue());
+                    }
+                    else
+                    {
+                        result = ep.getAttribute(attr.getName()).getValue().equals(attr.getValue());
+                    }
+                    break;
+                }
+                else if (ep.getAttribute(attr.getName()) == null)
+                {
+                    result = false;
+                    break;
+                }
+            }
+        }
+
+        // Check mandatory export attributes.
+        if (result)
+        {
+            result = ep.satisfies(this);
+        }
+
+        return result;
+    }
+
+    public String toString()
+    {
+        StringBuffer sb = new StringBuffer();
+        sb.append("import ");
+        sb.append(m_name);
+
+        if (m_attrs.size() > 0)
+        {
+            sb.append(" [");
+            for (Iterator<Entry<String, Attribute>> it = m_attrs.entrySet().iterator(); it.hasNext(); )
+            {
+                Entry<String, Attribute> entry = it.next();
+                sb.append(entry.getValue().getName());
+                sb.append('=');
+                sb.append(entry.getValue().getValue().toString());
+
+                if (it.hasNext())
+                {
+                    sb.append("; ");
+                }
+            }
+            sb.append("]");
+        }
+        return sb.toString();
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Main.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Main.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Main.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Main.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,533 @@
+/*
+ *  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.resolver;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.apache.felix.resolver.prototype.ProtoResolver;
+import org.apache.felix.resolver.felix.FelixResolver;
+
+public class Main
+{
+    public static void main(String[] args)
+    {
+        List<Module> moduleList = new ArrayList<Module>();
+
+        Module module = scenario5(moduleList);
+
+        Resolver resolver;
+        if ((args.length == 1) && (args[0].equals("-legacy")))
+        {
+            resolver = new FelixResolver(moduleList);
+        }
+        else
+        {
+            resolver = new ProtoResolver(moduleList);
+        }
+
+        try
+        {
+            long starttime = System.currentTimeMillis();
+            Map<Module, List<Wire>> wireMap = resolver.resolve(module);
+            long endtime = System.currentTimeMillis();
+            System.out.println("Resolve time: " + (endtime - starttime));
+            System.out.println("Wires:");
+            for (Iterator<Entry<Module, List<Wire>>> it = wireMap.entrySet().iterator();
+                it.hasNext(); )
+            {
+                Entry<Module, List<Wire>> entry = it.next();
+                if (entry.getValue().size() > 0)
+                {
+                    System.out.println("   " + entry.getKey());
+                    for (int i = 0; i < entry.getValue().size(); i++)
+                    {
+                        System.out.println("      " + entry.getValue().get(i));
+                    }
+                }
+            }
+        }
+        catch (Exception ex)
+        {
+            ex.printStackTrace(System.out);
+        }
+    }
+
+    // SOLUTION:
+    // A: bar->B, baz->E
+    // B: woz->D
+    // E: dit->F
+    private static Module scenario1(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("baz")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("bar").using("woz"))
+                .importing(new ImportedPackage("woz")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("woz").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("woz"))
+                .exporting(new ExportedPackage("unused")));
+        // Bundle E
+        moduleList.add(
+            new Module("E")
+                .exporting(new ExportedPackage("baz").using("dit"))
+                .exporting(new ExportedPackage("unused"))
+                .importing(new ImportedPackage("dit")));
+        // Bundle F
+        moduleList.add(
+            new Module("F")
+                .exporting(new ExportedPackage("dit").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // A: bar->B, woz->E
+    private static Module scenario2(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .exporting(new ExportedPackage("foo"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("woz")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("bar").using("baz,boo"))
+                .exporting(new ExportedPackage("baz"))
+                .exporting(new ExportedPackage("boo")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("woz").using("bar,dir"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("dit")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("dit").using("dot"))
+                .importing(new ImportedPackage("dot")));
+        // Bundle E
+        moduleList.add(
+            new Module("E")
+                .exporting(new ExportedPackage("dot").using("woz"))
+                .exporting(new ExportedPackage("woz")));
+        // Bundle F
+        moduleList.add(
+            new Module("F")
+                .exporting(new ExportedPackage("woz").using("bar"))
+                .importing(new ImportedPackage("bar")));
+        // Bundle G
+        moduleList.add(
+            new Module("G")
+                .exporting(new ExportedPackage("dot")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // A: bar->C, baz->D
+    private static Module scenario3(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .exporting(new ExportedPackage("foo"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("baz")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("bar").using("foo"))
+                .exporting(new ExportedPackage("baz").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("bar").using("woz"))
+                .exporting(new ExportedPackage("woz")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("baz")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // C: a->D, b->D, c->D, ..., foo->A, bar->A
+    private static Module scenario4(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            new Module("A")
+                .exporting(new ExportedPackage("bar").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("a").using("foo"))
+                .exporting(new ExportedPackage("b").using("foo"))
+                .exporting(new ExportedPackage("c").using("foo"))
+                .exporting(new ExportedPackage("d").using("foo"))
+                .exporting(new ExportedPackage("e").using("foo"))
+                .exporting(new ExportedPackage("f").using("foo"))
+                .exporting(new ExportedPackage("g").using("foo"))
+                .exporting(new ExportedPackage("h").using("foo"))
+                .exporting(new ExportedPackage("i").using("foo"))
+                .exporting(new ExportedPackage("j").using("foo"))
+                .exporting(new ExportedPackage("k").using("foo"))
+                .exporting(new ExportedPackage("l").using("foo"))
+                .exporting(new ExportedPackage("m").using("foo"))
+                .exporting(new ExportedPackage("n").using("foo"))
+                .exporting(new ExportedPackage("o").using("foo"))
+                .exporting(new ExportedPackage("p").using("foo"))
+                .exporting(new ExportedPackage("q").using("foo"))
+                .exporting(new ExportedPackage("r").using("foo"))
+                .exporting(new ExportedPackage("s").using("foo"))
+                .exporting(new ExportedPackage("t").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle C
+        moduleList.add(
+            target = new Module("C")
+                .importing(new ImportedPackage("a"))
+                .importing(new ImportedPackage("b"))
+                .importing(new ImportedPackage("c"))
+                .importing(new ImportedPackage("d"))
+                .importing(new ImportedPackage("e"))
+                .importing(new ImportedPackage("f"))
+                .importing(new ImportedPackage("g"))
+                .importing(new ImportedPackage("h"))
+                .importing(new ImportedPackage("i"))
+                .importing(new ImportedPackage("j"))
+                .importing(new ImportedPackage("k"))
+                .importing(new ImportedPackage("l"))
+                .importing(new ImportedPackage("m"))
+                .importing(new ImportedPackage("n"))
+                .importing(new ImportedPackage("o"))
+                .importing(new ImportedPackage("p"))
+                .importing(new ImportedPackage("q"))
+                .importing(new ImportedPackage("r"))
+                .importing(new ImportedPackage("s"))
+                .importing(new ImportedPackage("t"))
+                .importing(new ImportedPackage("foo"))
+                .importing(new ImportedPackage("bar")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("a"))
+                .exporting(new ExportedPackage("b"))
+                .exporting(new ExportedPackage("c"))
+                .exporting(new ExportedPackage("d"))
+                .exporting(new ExportedPackage("e"))
+                .exporting(new ExportedPackage("f"))
+                .exporting(new ExportedPackage("g"))
+                .exporting(new ExportedPackage("h"))
+                .exporting(new ExportedPackage("i"))
+                .exporting(new ExportedPackage("j"))
+                .exporting(new ExportedPackage("k"))
+                .exporting(new ExportedPackage("l"))
+                .exporting(new ExportedPackage("m"))
+                .exporting(new ExportedPackage("n"))
+                .exporting(new ExportedPackage("o"))
+                .exporting(new ExportedPackage("p"))
+                .exporting(new ExportedPackage("q"))
+                .exporting(new ExportedPackage("r"))
+                .exporting(new ExportedPackage("s"))
+                .exporting(new ExportedPackage("t")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // C: a->D, b->D, c->E, d->E, e->F, f->F, ..., foo->A, bar->A
+    private static Module scenario5(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            new Module("A")
+                .exporting(new ExportedPackage("bar").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("a").using("foo"))
+                .exporting(new ExportedPackage("b").using("foo"))
+                .exporting(new ExportedPackage("c").using("foo"))
+                .exporting(new ExportedPackage("d").using("foo"))
+                .exporting(new ExportedPackage("e").using("foo"))
+                .exporting(new ExportedPackage("f").using("foo"))
+                .exporting(new ExportedPackage("g").using("foo"))
+                .exporting(new ExportedPackage("h").using("foo"))
+                .exporting(new ExportedPackage("i").using("foo"))
+                .exporting(new ExportedPackage("j").using("foo"))
+                .exporting(new ExportedPackage("k").using("foo"))
+                .exporting(new ExportedPackage("l").using("foo"))
+                .exporting(new ExportedPackage("m").using("foo"))
+                .exporting(new ExportedPackage("n").using("foo"))
+                .exporting(new ExportedPackage("o").using("foo"))
+                .exporting(new ExportedPackage("p").using("foo"))
+                .exporting(new ExportedPackage("q").using("foo"))
+                .exporting(new ExportedPackage("r").using("foo"))
+                .exporting(new ExportedPackage("s").using("foo"))
+                .exporting(new ExportedPackage("t").using("foo"))
+                .exporting(new ExportedPackage("foo")));
+        // Bundle C
+        moduleList.add(
+            target = new Module("C")
+                .importing(new ImportedPackage("a"))
+                .importing(new ImportedPackage("b"))
+                .importing(new ImportedPackage("c"))
+                .importing(new ImportedPackage("d"))
+                .importing(new ImportedPackage("e"))
+                .importing(new ImportedPackage("f"))
+                .importing(new ImportedPackage("g"))
+                .importing(new ImportedPackage("h"))
+                .importing(new ImportedPackage("i"))
+                .importing(new ImportedPackage("j"))
+                .importing(new ImportedPackage("k"))
+                .importing(new ImportedPackage("l"))
+                .importing(new ImportedPackage("m"))
+                .importing(new ImportedPackage("n"))
+                .importing(new ImportedPackage("o"))
+                .importing(new ImportedPackage("p"))
+                .importing(new ImportedPackage("q"))
+                .importing(new ImportedPackage("r"))
+                .importing(new ImportedPackage("s"))
+                .importing(new ImportedPackage("t"))
+                .importing(new ImportedPackage("foo"))
+                .importing(new ImportedPackage("bar")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("a"))
+                .exporting(new ExportedPackage("b")));
+        // Bundle E
+        moduleList.add(
+            new Module("E")
+                .exporting(new ExportedPackage("c"))
+                .exporting(new ExportedPackage("d")));
+        // Bundle F
+        moduleList.add(
+            new Module("F")
+                .exporting(new ExportedPackage("e"))
+                .exporting(new ExportedPackage("f")));
+        // Bundle G
+        moduleList.add(
+            new Module("G")
+                .exporting(new ExportedPackage("g"))
+                .exporting(new ExportedPackage("h")));
+        // Bundle H
+        moduleList.add(
+            new Module("H")
+                .exporting(new ExportedPackage("i"))
+                .exporting(new ExportedPackage("j")));
+        // Bundle I
+        moduleList.add(
+            new Module("I")
+                .exporting(new ExportedPackage("k"))
+                .exporting(new ExportedPackage("l")));
+        // Bundle J
+        moduleList.add(
+            new Module("J")
+                .exporting(new ExportedPackage("m"))
+                .exporting(new ExportedPackage("n")));
+        // Bundle K
+        moduleList.add(
+            new Module("K")
+                .exporting(new ExportedPackage("o"))
+                .exporting(new ExportedPackage("p")));
+        // Bundle L
+        moduleList.add(
+            new Module("L")
+                .exporting(new ExportedPackage("q"))
+                .exporting(new ExportedPackage("r")));
+        // Bundle M
+        moduleList.add(
+            new Module("M")
+                .exporting(new ExportedPackage("s"))
+                .exporting(new ExportedPackage("t")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // A: baz cannot be resolved
+    private static Module scenario6(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .importing(new ImportedPackage("foo"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("baz")
+                    .with("attr=blah")));
+
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("foo").using("bar"))
+                .exporting(new ExportedPackage("bar").using("baz"))
+                .exporting(new ExportedPackage("baz")));
+
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("baz")
+                    .with("attr=blah")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // A: bar->B
+    // B: woz->C
+    // C: foo->A
+    private static Module scenario7(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .exporting(new ExportedPackage("foo"))
+                .importing(new ImportedPackage("bar")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("bar"))
+                .importing(new ImportedPackage("woz")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("woz"))
+                .importing(new ImportedPackage("foo")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // A: bar->C, baz->B
+    private static Module scenario8(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            target = new Module("A")
+                .exporting(new ExportedPackage("foo"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("baz")));
+        // Bundle B
+        moduleList.add(
+            new Module("B")
+                .exporting(new ExportedPackage("foo"))
+                .exporting(new ExportedPackage("bar").using("foo"))
+                .exporting(new ExportedPackage("baz")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("bar")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // B: foo->C, foobar->A, bar->C, baz->C
+    private static Module scenario9(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            new Module("A")
+                .exporting(new ExportedPackage("foo"))
+                .exporting(new ExportedPackage("foobar"))
+                .exporting(new ExportedPackage("bar").using("foo")));
+        // Bundle B
+        moduleList.add(
+            target = new Module("B")
+                .importing(new ImportedPackage("foo"))
+                .importing(new ImportedPackage("foobar"))
+                .importing(new ImportedPackage("bar"))
+                .importing(new ImportedPackage("baz")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("foo"))
+                .exporting(new ExportedPackage("bar").using("foo"))
+                .exporting(new ExportedPackage("baz").using("bar")));
+        // Bundle D
+        moduleList.add(
+            new Module("D")
+                .exporting(new ExportedPackage("bar")));
+
+        return target;
+    }
+
+    // SOLUTION:
+    // B: foo->C
+    private static Module scenario10(List<Module> moduleList)
+    {
+        Module target;
+
+        // Bundle A
+        moduleList.add(
+            new Module("A")
+                .exporting(new ExportedPackage("foo").withMandatory("vendor=foo")));
+        // Bundle B
+        moduleList.add(
+            target = new Module("B")
+                .importing(new ImportedPackage("foo")));
+        // Bundle C
+        moduleList.add(
+            new Module("C")
+                .exporting(new ExportedPackage("foo")));
+
+        return target;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Module.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Module.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Module.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Module.java Tue Aug 25 20:30:33 2009
@@ -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.resolver;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Module
+{
+    private final String m_name;
+    private final List<ExportedPackage> m_exports;
+    private final List<ImportedPackage> m_imports;
+    private boolean m_isResolved = false;
+
+    public Module(String name)
+    {
+        m_name = name;
+        m_exports = new ArrayList<ExportedPackage>();
+        m_imports = new ArrayList<ImportedPackage>();
+    }
+
+    public String getName()
+    {
+        return m_name;
+    }
+
+    public Module exporting(ExportedPackage ep)
+    {
+        m_exports.add(ep);
+        return this;
+    }
+
+    public Module importing(ImportedPackage ip)
+    {
+        m_imports.add(ip);
+        return this;
+    }
+
+    public List<ExportedPackage> getExports()
+    {
+        return m_exports;
+    }
+
+    public List<ImportedPackage> getImports()
+    {
+        return m_imports;
+    }
+
+    public synchronized void resolve()
+    {
+        m_isResolved = true;
+    }
+
+    public synchronized boolean isResolved()
+    {
+        return m_isResolved;
+    }
+
+    public String toString()
+    {
+        return m_name;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolveException.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolveException.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolveException.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolveException.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,31 @@
+/*
+ *  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.resolver;
+
+public class ResolveException extends RuntimeException
+{
+    /**
+     * Constructs an instance of <code>ResolveException</code> with the specified detail message.
+     * @param msg the detail message.
+     */
+    public ResolveException(String msg)
+    {
+        super(msg);
+    }
+}

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Resolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Resolver.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Resolver.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Resolver.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,29 @@
+/*
+ *  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.resolver;
+
+import java.util.List;
+import java.util.Map;
+
+public interface Resolver
+{
+    Module getModule(String name);
+
+    Map<Module, List<Wire>> resolve(Module module);
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolverConflictException.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolverConflictException.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolverConflictException.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/ResolverConflictException.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,34 @@
+/*
+ *  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.resolver;
+
+import java.util.List;
+import java.util.Map;
+
+public class ResolverConflictException extends RuntimeException
+{
+    /**
+     * Constructs an instance of <code>ResolverConflictException</code> with the specified detail message.
+     * @param msg the detail message.
+     */
+    public ResolverConflictException(String msg)
+    {
+        super(msg);
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Version.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Version.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Version.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Version.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,368 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2009). All Rights Reserved.
+ * 
+ * Licensed 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.resolver;
+
+import java.util.NoSuchElementException;
+import java.util.StringTokenizer;
+
+/**
+ * Version identifier for bundles and packages.
+ * 
+ * <p>
+ * Version identifiers have four components.
+ * <ol>
+ * <li>Major version. A non-negative integer.</li>
+ * <li>Minor version. A non-negative integer.</li>
+ * <li>Micro version. A non-negative integer.</li>
+ * <li>Qualifier. A text string. See <code>Version(String)</code> for the
+ * format of the qualifier string.</li>
+ * </ol>
+ * 
+ * <p>
+ * <code>Version</code> objects are immutable.
+ * 
+ * @since 1.3
+ * @Immutable
+ * @version $Revision: 6860 $
+ */
+
+public class Version implements Comparable {
+	private final int			major;
+	private final int			minor;
+	private final int			micro;
+	private final String		qualifier;
+	private static final String	SEPARATOR		= ".";					//$NON-NLS-1$
+
+	/**
+	 * The empty version "0.0.0".
+	 */
+	public static final Version	emptyVersion	= new Version(0, 0, 0);
+
+	/**
+	 * Creates a version identifier from the specified numerical components.
+	 * 
+	 * <p>
+	 * The qualifier is set to the empty string.
+	 * 
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @throws IllegalArgumentException If the numerical components are
+	 *         negative.
+	 */
+	public Version(int major, int minor, int micro) {
+		this(major, minor, micro, null);
+	}
+
+	/**
+	 * Creates a version identifier from the specified components.
+	 * 
+	 * @param major Major component of the version identifier.
+	 * @param minor Minor component of the version identifier.
+	 * @param micro Micro component of the version identifier.
+	 * @param qualifier Qualifier component of the version identifier. If
+	 *        <code>null</code> is specified, then the qualifier will be set to
+	 *        the empty string.
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	public Version(int major, int minor, int micro, String qualifier) {
+		if (qualifier == null) {
+			qualifier = ""; //$NON-NLS-1$
+		}
+
+		this.major = major;
+		this.minor = minor;
+		this.micro = micro;
+		this.qualifier = qualifier;
+		validate();
+	}
+
+	/**
+	 * Created a version identifier from the specified string.
+	 * 
+	 * <p>
+	 * Here is the grammar for version strings.
+	 * 
+	 * <pre>
+	 * version ::= major('.'minor('.'micro('.'qualifier)?)?)?
+	 * major ::= digit+
+	 * minor ::= digit+
+	 * micro ::= digit+
+	 * qualifier ::= (alpha|digit|'_'|'-')+
+	 * digit ::= [0..9]
+	 * alpha ::= [a..zA..Z]
+	 * </pre>
+	 * 
+	 * There must be no whitespace in version.
+	 * 
+	 * @param version String representation of the version identifier.
+	 * @throws IllegalArgumentException If <code>version</code> is improperly
+	 *         formatted.
+	 */
+	public Version(String version) {
+		int maj = 0;
+		int min = 0;
+		int mic = 0;
+		String qual = ""; //$NON-NLS-1$
+
+		try {
+			StringTokenizer st = new StringTokenizer(version, SEPARATOR, true);
+			maj = Integer.parseInt(st.nextToken());
+
+			if (st.hasMoreTokens()) {
+				st.nextToken(); // consume delimiter
+				min = Integer.parseInt(st.nextToken());
+
+				if (st.hasMoreTokens()) {
+					st.nextToken(); // consume delimiter
+					mic = Integer.parseInt(st.nextToken());
+
+					if (st.hasMoreTokens()) {
+						st.nextToken(); // consume delimiter
+						qual = st.nextToken();
+
+						if (st.hasMoreTokens()) {
+							throw new IllegalArgumentException("invalid format"); //$NON-NLS-1$
+						}
+					}
+				}
+			}
+		}
+		catch (NoSuchElementException e) {
+			throw new IllegalArgumentException("invalid format"); //$NON-NLS-1$
+		}
+
+		major = maj;
+		minor = min;
+		micro = mic;
+		qualifier = qual;
+		validate();
+	}
+
+	/**
+	 * Called by the Version constructors to validate the version components.
+	 * 
+	 * @throws IllegalArgumentException If the numerical components are negative
+	 *         or the qualifier string is invalid.
+	 */
+	private void validate() {
+		if (major < 0) {
+			throw new IllegalArgumentException("negative major"); //$NON-NLS-1$
+		}
+		if (minor < 0) {
+			throw new IllegalArgumentException("negative minor"); //$NON-NLS-1$
+		}
+		if (micro < 0) {
+			throw new IllegalArgumentException("negative micro"); //$NON-NLS-1$
+		}
+		char[] chars = qualifier.toCharArray();
+		for (int i = 0, length = chars.length; i < length; i++) {
+	        char ch = chars[i];
+			if (('A' <= ch) && (ch <= 'Z')) {
+				continue;
+			}
+			if (('a' <= ch) && (ch <= 'z')) {
+				continue;
+			}
+			if (('0' <= ch) && (ch <= '9')) {
+				continue;
+			}
+			if ((ch == '_') || (ch == '-')) {
+				continue;
+			}
+			throw new IllegalArgumentException(
+					"invalid qualifier: " + qualifier); //$NON-NLS-1$
+		}
+	}
+
+	/**
+	 * Parses a version identifier from the specified string.
+	 * 
+	 * <p>
+	 * See <code>Version(String)</code> for the format of the version string.
+	 * 
+	 * @param version String representation of the version identifier. Leading
+	 *        and trailing whitespace will be ignored.
+	 * @return A <code>Version</code> object representing the version
+	 *         identifier. If <code>version</code> is <code>null</code> or
+	 *         the empty string then <code>emptyVersion</code> will be
+	 *         returned.
+	 * @throws IllegalArgumentException If <code>version</code> is improperly
+	 *         formatted.
+	 */
+	public static Version parseVersion(String version) {
+		if (version == null) {
+			return emptyVersion;
+		}
+
+		version = version.trim();
+		if (version.length() == 0) {
+			return emptyVersion;
+		}
+
+		return new Version(version);
+	}
+
+	/**
+	 * Returns the major component of this version identifier.
+	 * 
+	 * @return The major component.
+	 */
+	public int getMajor() {
+		return major;
+	}
+
+	/**
+	 * Returns the minor component of this version identifier.
+	 * 
+	 * @return The minor component.
+	 */
+	public int getMinor() {
+		return minor;
+	}
+
+	/**
+	 * Returns the micro component of this version identifier.
+	 * 
+	 * @return The micro component.
+	 */
+	public int getMicro() {
+		return micro;
+	}
+
+	/**
+	 * Returns the qualifier component of this version identifier.
+	 * 
+	 * @return The qualifier component.
+	 */
+	public String getQualifier() {
+		return qualifier;
+	}
+
+	/**
+	 * Returns the string representation of this version identifier.
+	 * 
+	 * <p>
+	 * The format of the version string will be <code>major.minor.micro</code>
+	 * if qualifier is the empty string or
+	 * <code>major.minor.micro.qualifier</code> otherwise.
+	 * 
+	 * @return The string representation of this version identifier.
+	 */
+	public String toString() {
+		int q = qualifier.length();
+		StringBuffer result = new StringBuffer(20 + q);
+		result.append(major);
+		result.append(SEPARATOR);
+		result.append(minor);
+		result.append(SEPARATOR);
+		result.append(micro);
+		if (q > 0) {
+			result.append(SEPARATOR);
+			result.append(qualifier);
+		}
+		return result.toString();
+	}
+
+	/**
+	 * Returns a hash code value for the object.
+	 * 
+	 * @return An integer which is a hash code value for this object.
+	 */
+	public int hashCode() {
+		return (major << 24) + (minor << 16) + (micro << 8)
+				+ qualifier.hashCode();
+	}
+
+	/**
+	 * Compares this <code>Version</code> object to another object.
+	 * 
+	 * <p>
+	 * A version is considered to be <b>equal to </b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using <code>String.equals</code>).
+	 * 
+	 * @param object The <code>Version</code> object to be compared.
+	 * @return <code>true</code> if <code>object</code> is a
+	 *         <code>Version</code> and is equal to this object;
+	 *         <code>false</code> otherwise.
+	 */
+	public boolean equals(Object object) {
+		if (object == this) { // quicktest
+			return true;
+		}
+
+		if (!(object instanceof Version)) {
+			return false;
+		}
+
+		Version other = (Version) object;
+		return (major == other.major) && (minor == other.minor)
+				&& (micro == other.micro) && qualifier.equals(other.qualifier);
+	}
+
+	/**
+	 * Compares this <code>Version</code> object to another object.
+	 * 
+	 * <p>
+	 * A version is considered to be <b>less than </b> another version if its
+	 * major component is less than the other version's major component, or the
+	 * major components are equal and its minor component is less than the other
+	 * version's minor component, or the major and minor components are equal
+	 * and its micro component is less than the other version's micro component,
+	 * or the major, minor and micro components are equal and it's qualifier
+	 * component is less than the other version's qualifier component (using
+	 * <code>String.compareTo</code>).
+	 * 
+	 * <p>
+	 * A version is considered to be <b>equal to</b> another version if the
+	 * major, minor and micro components are equal and the qualifier component
+	 * is equal (using <code>String.compareTo</code>).
+	 * 
+	 * @param object The <code>Version</code> object to be compared.
+	 * @return A negative integer, zero, or a positive integer if this object is
+	 *         less than, equal to, or greater than the specified
+	 *         <code>Version</code> object.
+	 * @throws ClassCastException If the specified object is not a
+	 *         <code>Version</code>.
+	 */
+	public int compareTo(Object object) {
+		if (object == this) { // quicktest
+			return 0;
+		}
+
+		Version other = (Version) object;
+
+		int result = major - other.major;
+		if (result != 0) {
+			return result;
+		}
+
+		result = minor - other.minor;
+		if (result != 0) {
+			return result;
+		}
+
+		result = micro - other.micro;
+		if (result != 0) {
+			return result;
+		}
+
+		return qualifier.compareTo(other.qualifier);
+	}
+}

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/VersionRange.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/VersionRange.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/VersionRange.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/VersionRange.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,162 @@
+/* 
+ * 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.resolver;
+
+import org.apache.felix.resolver.Version;
+
+public class VersionRange
+{
+    private Version m_low = null;
+    private boolean m_isLowInclusive = false;
+    private Version m_high = null;
+    private boolean m_isHighInclusive = false;
+    private String m_toString = null;
+    public static final VersionRange infiniteRange = new VersionRange(Version.emptyVersion, true, null, true);
+
+    public VersionRange(Version low, boolean isLowInclusive,
+        Version high, boolean isHighInclusive)
+    {
+        m_low = low;
+        m_isLowInclusive = isLowInclusive;
+        m_high = high;
+        m_isHighInclusive = isHighInclusive;
+    }
+
+    public Version getLow()
+    {
+        return m_low;
+    }
+
+    public boolean isLowInclusive()
+    {
+        return m_isLowInclusive;
+    }
+
+    public Version getHigh()
+    {
+        return m_high;
+    }
+
+    public boolean isHighInclusive()
+    {
+        return m_isHighInclusive;
+    }
+
+    public boolean isInRange(Version version)
+    {
+        // We might not have an upper end to the range.
+        if (m_high == null)
+        {
+            return (version.compareTo(m_low) >= 0);
+        }
+        else if (isLowInclusive() && isHighInclusive())
+        {
+            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) <= 0);
+        }
+        else if (isHighInclusive())
+        {
+            return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) <= 0);
+        }
+        else if (isLowInclusive())
+        {
+            return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) < 0);
+        }
+        return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) < 0);
+    }
+
+    public static VersionRange parse(String range)
+    {
+        // Check if the version is an interval.
+        if (range.indexOf(',') >= 0)
+        {
+            String s = range.substring(1, range.length() - 1);
+            String vlo = s.substring(0, s.indexOf(',')).trim();
+            String vhi = s.substring(s.indexOf(',') + 1, s.length()).trim();
+            return new VersionRange (
+                new Version(vlo), (range.charAt(0) == '['),
+                new Version(vhi), (range.charAt(range.length() - 1) == ']'));
+        }
+        else
+        {
+            return new VersionRange(new Version(range), true, null, false);
+        }
+    }
+
+    public boolean equals(Object obj)
+    {
+        if (obj == null)
+        {
+            return false;
+        }
+        if (getClass() != obj.getClass())
+        {
+            return false;
+        }
+        final VersionRange other = (VersionRange) obj;
+        if (m_low != other.m_low && (m_low == null || !m_low.equals(other.m_low)))
+        {
+            return false;
+        }
+        if (m_isLowInclusive != other.m_isLowInclusive)
+        {
+            return false;
+        }
+        if (m_high != other.m_high && (m_high == null || !m_high.equals(other.m_high)))
+        {
+            return false;
+        }
+        if (m_isHighInclusive != other.m_isHighInclusive)
+        {
+            return false;
+        }
+        return true;
+    }
+
+    public int hashCode()
+    {
+        int hash = 5;
+        hash = 97 * hash + (m_low != null ? m_low.hashCode() : 0);
+        hash = 97 * hash + (m_isLowInclusive ? 1 : 0);
+        hash = 97 * hash + (m_high != null ? m_high.hashCode() : 0);
+        hash = 97 * hash + (m_isHighInclusive ? 1 : 0);
+        return hash;
+    }
+
+    public String toString()
+    {
+        if (m_toString == null)
+        {
+            if (m_high != null)
+            {
+                StringBuffer sb = new StringBuffer();
+                sb.append(m_isLowInclusive ? '[' : '(');
+                sb.append(m_low.toString());
+                sb.append(',');
+                sb.append(m_high.toString());
+                sb.append(m_isHighInclusive ? ']' : ')');
+                m_toString = sb.toString();
+            }
+            else
+            {
+                m_toString = m_low.toString();
+            }
+        }
+        return m_toString;
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Wire.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Wire.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Wire.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/Wire.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,60 @@
+/*
+ *  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.resolver;
+
+public class Wire
+{
+    private final Module m_importer;
+    private final ImportedPackage m_ip;
+    private final Module m_exporter;
+    private final ExportedPackage m_ep;
+
+    public Wire(Module importer, ImportedPackage ip, Module exporter, ExportedPackage ep)
+    {
+        m_importer = importer;
+        m_ip = ip;
+        m_exporter = exporter;
+        m_ep = ep;
+    }
+
+    public Module getImporter()
+    {
+        return m_importer;
+    }
+
+    public ImportedPackage getImportedPackage()
+    {
+        return m_ip;
+    }
+
+    public Module getExporter()
+    {
+        return m_exporter;
+    }
+
+    public ExportedPackage getExportedPackage()
+    {
+        return m_ep;
+    }
+
+    public String toString()
+    {
+        return "WIRE: " + m_ip + " (" + m_importer + ") -> " + m_ep + " (" + m_exporter + ")";
+    }
+}
\ No newline at end of file

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/CandidateSet.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/CandidateSet.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/CandidateSet.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/CandidateSet.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,55 @@
+/*
+ * 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.resolver.felix;
+
+import org.apache.felix.resolver.*;
+
+class CandidateSet
+{
+    public static final int NORMAL = 0;
+    public static final int FRAGMENT = 1;
+    public static final int HOST = 2;
+    public final int m_type;
+    public final Module m_module;
+    public final ImportedPackage m_requirement;
+    public final PackageSource[] m_candidates;
+    public final Module[] m_modules;
+    public int m_idx = 0;
+    public int m_rotated = 0;
+
+    public CandidateSet(int type, Module module, ImportedPackage requirement, PackageSource[] candidates)
+    {
+        super();
+        m_type = type;
+        m_module = module;
+        m_requirement = requirement;
+        m_candidates = candidates;
+        m_modules = null;
+    }
+
+    public CandidateSet(int type, Module module, ImportedPackage requirement, Module[] fragments)
+    {
+        super();
+        m_type = type;
+        m_module = module;
+        m_requirement = requirement;
+        m_candidates = null;
+        m_modules = fragments;
+    }
+}

Added: felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolver.java
URL: http://svn.apache.org/viewvc/felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolver.java?rev=807795&view=auto
==============================================================================
--- felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolver.java (added)
+++ felix/sandbox/rickhall/resolver/src/main/java/org/apache/felix/resolver/felix/FelixResolver.java Tue Aug 25 20:30:33 2009
@@ -0,0 +1,102 @@
+/*
+ *  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.resolver.felix;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.felix.resolver.ExportedPackage;
+import org.apache.felix.resolver.ImportedPackage;
+import org.apache.felix.resolver.Module;
+import org.apache.felix.resolver.Resolver;
+import org.apache.felix.resolver.Wire;
+
+public class FelixResolver implements Resolver
+{
+    private final List<Module> m_moduleList;
+    private final Module[] m_modules;
+    private final FelixResolverImpl m_resolver = new FelixResolverImpl();
+    private final ResolverStateImpl m_state = new ResolverStateImpl();
+
+    public FelixResolver(List<Module> moduleList)
+    {
+        m_moduleList = moduleList;
+        m_modules = (Module[]) moduleList.toArray(new Module[moduleList.size()]);
+    }
+
+    public Module getModule(String name)
+    {
+        for (int i = 0; i < m_modules.length; i++)
+        {
+            if (m_modules[i].getName().equals(name))
+            {
+                return m_modules[i];
+            }
+        }
+        return null;
+    }
+
+    public Map<Module, List<Wire>> resolve(Module module)
+    {
+System.out.println("+++ FELIX RESOLVER");
+        Map wireMap = m_resolver.resolve(m_state, module);
+        Map<Module, List<Wire>> newWireMap = new HashMap<Module, List<Wire>>();
+        for (Iterator it = wireMap.entrySet().iterator(); it.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            Module m = (Module) entry.getKey();
+            Wire[] wires = (Wire[]) entry.getValue();
+            newWireMap.put(m, Arrays.asList(wires));
+        }
+        return newWireMap;
+    }
+
+    private class ResolverStateImpl implements FelixResolverImpl.ResolverState
+    {
+        public Module[] getModules()
+        {
+            return m_modules;
+        }
+
+        public PackageSource[] getResolvedCandidates(ImportedPackage req)
+        {
+            return new PackageSource[0];
+        }
+
+        public PackageSource[] getUnresolvedCandidates(ImportedPackage req)
+        {
+            List<PackageSource> ps = new ArrayList<PackageSource>();
+            for (int modIdx = 0; modIdx < m_modules.length; modIdx++)
+            {
+                List<ExportedPackage> exports = m_modules[modIdx].getExports();
+                for (int expIdx = 0; expIdx < exports.size(); expIdx++)
+                {
+                    if (req.isSatistfiedBy(exports.get(expIdx)))
+                    {
+                        ps.add(new PackageSource(m_modules[modIdx], exports.get(expIdx)));
+                    }
+                }
+            }
+            return ps.toArray(new PackageSource[ps.size()]);
+        }
+    }
+}
\ No newline at end of file



Mime
View raw message