FELIX-2144: API changes:
- remove Resolver#getGlobalRequirements and Resolver#addGlobalRequirement(Requirement)
- add RepositoryAdmin#repository(Resource[]) to create an in memory repository
- remove Capability#getResource()
- remove Requirement#getResource()
- remove Resource#getRepository()
- move Repository#isLocal() to Resource#isLocal()
- new interface Reason (pair of Requirement / Resource)
- change Resolver to use Reason[] for resource selection explanation and unsatisfied requirements

Additional minor changes:
- discoverResources(String) nows throws an InvalidSyntaxException
- remove RepositoryAdmin#deploy(boolean) deprecated to #deploy(int)
- improve resolver by using List instead of arrays for holding reasons / unsatisfied reqs
- add missing ASF headers

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@917934 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
index c179ac1..4ddba95 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Capability.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Capability.java,v 1.3 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -46,10 +64,4 @@
      */
     Map getProperties();
 
-    /**
-     * Return the resource this capability belongs to
-     *
-     * @return the resource
-     */
-    Resource getResource();
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Reason.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Reason.java
new file mode 100644
index 0000000..b74daab
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Reason.java
@@ -0,0 +1,33 @@
+/*
+ * 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.bundlerepository;
+
+/**
+ * A pair of requirement and resource indicating a reason
+ * why a resource has been chosen.
+ * The reason indicates which resource and which requirement
+ * has been satisfied by the selected resource.
+ */
+public interface Reason {
+
+    Resource getResource();
+
+    Requirement getRequirement();
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Repository.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Repository.java
index c47ea95..9ee805b 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Repository.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Repository.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Repository.java,v 1.3 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -55,14 +73,4 @@
      */
     long getLastModified();
 
-    /**
-     * Returns whether this repository is a local one
-     * or not.
-     *
-     * Local repositories contains resources that are already available
-     * in the OSGi framework and thus will be preferred over other
-     * resources.
-     */
-    boolean isLocal();
-
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
index 8a9d9bc..5b69004 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/RepositoryAdmin.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/RepositoryAdmin.java,v 1.3 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -74,7 +92,7 @@
      *            A standard OSGi filter
      * @return List of resources matching the filters.
      */
-    Resource[] discoverResources(String filterExpr);
+    Resource[] discoverResources(String filterExpr) throws InvalidSyntaxException;
 
     /**
      * Discover any resources that match the given requirements.
@@ -146,6 +164,7 @@
      * @param name
      * @param filter
      * @return
+     * @throws InvalidSyntaxException
      */
     Requirement requirement(String name, String filter) throws InvalidSyntaxException;
 
@@ -154,6 +173,7 @@
      *
      * @param filter the string filter
      * @return
+     * @throws InvalidSyntaxException
      */
     Filter filter(String filter) throws InvalidSyntaxException;
 
@@ -162,15 +182,27 @@
      * 
      * @param repository
      * @return
+     * @throws Exception
      */
     Repository repository(URL repository) throws Exception;
 
     /**
+     * Create a repository for the given set of resources.
+     * Such repositories can be used to create a resolver
+     * that would resolve on a subset of available resources
+     * instead of all of them.
+     *
+     * @param resources an array of resources
+     * @return a repository containing the given resources
+     */
+    Repository repository(Resource[] resources);
+
+    /**
      * Create a capability
      *
      * @param name name of this capability
      * @param properties the properties
-     * @return
+     * @return a new capability with the specified name and properties
      */
     Capability capability(String name, Map properties);
 
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java
index c45549b..bd49d0d 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Requirement.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Requirement.java,v 1.4 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -24,6 +42,12 @@
 /**
  * A named requirement specifies the need for certain capabilities with the same
  * name.
+ *
+ * A requirement is said to be satisfied by a capability if and only if:
+ * <ul>
+ *   <li>they have the same nsame</li>
+ *   <li>the filter matches the capability properties</li>
+ * </ul>
  * 
  * @version $Revision: 1.4 $
  */
@@ -37,7 +61,6 @@
 
     /**
      * Return the filter.
-     * 
      */
     String getFilter();
 
@@ -57,11 +80,4 @@
      */
     boolean isSatisfied(Capability capability);
 
-    /**
-     * Return the resource this requirement belongs to
-     * or <code>null</code
-     *
-     * @return the resource
-     */
-    Resource getResource();
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
index a5e059d..42e9dab 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resolver.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Resolver.java,v 1.3 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -82,27 +100,6 @@
      */
     Capability[] getGlobalCapabilities();
 
-    /**
-     * Add a global requirement.
-     *
-     * A global requirement is a requirement that must be satisfied by all
-     * resources.  Such requirements are usually built using an
-     *    IF x then Y
-     * which can be expressed using the following logical expression
-     *    !X OR (X AND Y)
-     * which can be translated to the following filter
-     *    (|(!(x))(&(x)(y))
-     *
-     * @param requirement
-     */
-    void addGlobalRequirement(Requirement requirement);
-
-    /**
-     * Returns a list of global requirements
-     * @return
-     */
-    Requirement[] getGlobalRequirements();
-
    /**
      * Start the resolution process and return whether the constraints have
      * been successfully met or not.
@@ -122,17 +119,32 @@
      */
     boolean resolve(int flags) throws InterruptedResolutionException;
 
-    Requirement[] getUnsatisfiedRequirements();
-
-    Resource[] getOptionalResources();
-
-    Requirement[] getReason(Resource resource);
-
-    Resource[] getResources(Requirement requirement);
-
+    /**
+     * List of mandatory resources that need to be installed
+     * @return
+     */
     Resource[] getRequiredResources();
 
-    void deploy(boolean start);
+    /**
+     * List of optional resources that may be installed
+     * @return
+     */
+    Resource[] getOptionalResources();
+
+    /**
+     * List of reasons why a resource has been included either as a mandatory or
+     * optional resource during the resolution.
+     *
+     * @param resource
+     * @return an array of Reason
+     */
+    Reason[] getReason(Resource resource);
+
+    /**
+     * List of requirements that could not be satisfied during the resolution
+     * @return
+     */
+    Reason[] getUnsatisfiedRequirements();
 
     void deploy(int flags);
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
index 4e7eede..9af2de6 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/Resource.java
@@ -1,4 +1,22 @@
 /*
+ * 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.
+ */
+/*
  * $Header: /cvshome/build/org.osgi.service.obr/src/org/osgi/service/obr/Resource.java,v 1.5 2006/03/16 14:56:17 hargrave Exp $
  *
  * Copyright (c) OSGi Alliance (2006). All Rights Reserved.
@@ -46,6 +64,8 @@
 
     final String SOURCE_URL = "source";
 
+    final String JAVADOC_URL = "javadoc";
+
     final String SYMBOLIC_NAME = "symbolicname";
 
     final String PRESENTATION_NAME = "presentationname";
@@ -60,8 +80,6 @@
 
     final String CATEGORY = "category";
 
-    final String JAVADOC = "javadoc";
-
     // get readable name
 
     Map getProperties();
@@ -82,6 +100,12 @@
 
     String[] getCategories();
 
-    Repository getRepository();
+    /**
+     * Returns whether this resource is a local one or not.
+     *
+     * Local resources are already available in the OSGi framework and thus will be
+     * preferred over other resources.
+     */
+    boolean isLocal();
 
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
index 01f6542..376d82a 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/CapabilityImpl.java
@@ -25,7 +25,6 @@
 
 public class CapabilityImpl implements Capability
 {
-    private ResourceImpl m_resource;
     private String m_name = null;
     private final Map m_map = new HashMap();
 
@@ -33,16 +32,6 @@
     {
     }
 
-    public Resource getResource()
-    {
-        return m_resource;
-    }
-
-    public void setResource(ResourceImpl resource)
-    {
-        m_resource = resource;
-    }
-
     public String getName()
     {
         return m_name;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
index e28a874..038ff10 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalRepositoryImpl.java
@@ -143,11 +143,6 @@
         return (Resource[]) m_localResourceList.values().toArray(new Resource[m_localResourceList.size()]);
     }
 
-    public boolean isLocal()
-    {
-        return true;
-    }
-
     private void initialize()
     {
         // register for bundle and service events now
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
index 0690d44..72fd15e 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/LocalResourceImpl.java
@@ -49,6 +49,11 @@
         initialize();
     }
 
+    public boolean isLocal()
+    {
+        return true;
+    }
+
     public Bundle getBundle()
     {
         return m_bundle;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
index 90350ab..6637974 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrCommandImpl.java
@@ -24,7 +24,9 @@
 import java.util.*;
 
 import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Reason;
 import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
 import org.apache.felix.bundlerepository.Resource;
 import org.apache.felix.shell.Command;
 import org.osgi.framework.*;
@@ -396,7 +398,7 @@
                 try
                 {
                     out.print("\nDeploying...");
-                    resolver.deploy(command.equals(START_CMD));
+                    resolver.deploy(command.equals(START_CMD) ? Resolver.START : 0);
                     out.println("done.");
                 }
                 catch (IllegalStateException ex)
@@ -406,19 +408,15 @@
             }
             else
             {
-                Requirement[] reqs = resolver.getUnsatisfiedRequirements();
+                Reason[] reqs = resolver.getUnsatisfiedRequirements();
                 if ((reqs != null) && (reqs.length > 0))
                 {
                     out.println("Unsatisfied requirement(s):");
                     printUnderline(out, 27);
                     for (int reqIdx = 0; reqIdx < reqs.length; reqIdx++)
                     {
-                        out.println("   " + reqs[reqIdx].getFilter());
-                        Resource[] resources = resolver.getResources(reqs[reqIdx]);
-                        for (int resIdx = 0; resIdx < resources.length; resIdx++)
-                        {
-                            out.println("      " + resources[resIdx].getPresentationName());
-                        }
+                        out.println("   " + reqs[reqIdx].getRequirement().getFilter());
+                        out.println("      " + reqs[reqIdx].getResource().getPresentationName());
                     }
                 }
                 else
@@ -491,7 +489,7 @@
         }
     }
 
-    private Resource[] searchRepository(String targetId, String targetVersion)
+    private Resource[] searchRepository(String targetId, String targetVersion) throws InvalidSyntaxException
     {
         // Try to see if the targetId is a bundle ID.
         try
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
index 568da7c..35a26ca 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ObrURLStreamHandlerService.java
@@ -109,22 +109,29 @@
 
         URL remoteURL = null;
 
-        Bundle[] bundles = m_bundleContext.getBundles();
-
-        int i = 0;
-        while ((remoteURL == null) && (i < bundles.length))
+        try
         {
-            if (url.equals(bundles[i].getLocation()))
+            Bundle[] bundles = m_bundleContext.getBundles();
+
+            int i = 0;
+            while ((remoteURL == null) && (i < bundles.length))
             {
-                remoteURL = getRemoteUrlForBundle(bundles[i]);
+                if (url.equals(bundles[i].getLocation()))
+                {
+                    remoteURL = getRemoteUrlForBundle(bundles[i]);
+                }
+                i++;
             }
-            i++;
-        }
 
-        if (remoteURL == null)
+            if (remoteURL == null)
+            {
+                String path = u.getPath();
+                remoteURL = getRemoteObrInstallUrl(path);
+            }
+        }
+        catch (InvalidSyntaxException e)
         {
-            String path = u.getPath();
-            remoteURL = getRemoteObrInstallUrl(path);
+            throw (IOException) new IOException().initCause(e);
         }
 
         return remoteURL.openConnection();
@@ -140,7 +147,7 @@
      * @return the remote URL of the resolved bundle
      * @throws IOException if an error occurs
      */
-    private URL getRemoteObrInstallUrl(String path) throws IOException
+    private URL getRemoteObrInstallUrl(String path) throws IOException, InvalidSyntaxException
     {
         if( path == null || path.trim().length() == 0 )
         {
@@ -199,7 +206,7 @@
      * @return remote url
      * @throws IOException if something went wrong
      */
-    private URL getRemoteUrlForBundle(Bundle bundle) throws IOException
+    private URL getRemoteUrlForBundle(Bundle bundle) throws IOException, InvalidSyntaxException
     {
         String symbolicName = bundle.getSymbolicName();
         String version = (String) bundle.getHeaders().get(Constants.BUNDLE_VERSION);
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ReasonImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ReasonImpl.java
new file mode 100644
index 0000000..d3bc3ca
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ReasonImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.bundlerepository.impl;
+
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+
+public class ReasonImpl implements Reason
+{
+
+    private final Resource resource;
+    private final Requirement requirement;
+
+    public ReasonImpl(Resource resource, Requirement requirement)
+    {
+        this.resource = resource;
+        this.requirement = requirement;
+    }
+
+    public Resource getResource()
+    {
+        return resource;
+    }
+
+    public Requirement getRequirement()
+    {
+        return requirement;
+    }
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
index 9e59ada..f169eed 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryAdminImpl.java
@@ -119,12 +119,10 @@
         {
             initialize();
         }
-
         List repositories = new ArrayList();
         repositories.add(m_system);
         repositories.add(m_local);
         repositories.addAll(m_repoMap.values());
-
         return resolver((Repository[]) repositories.toArray(new Repository[repositories.size()]));
     }
 
@@ -134,32 +132,22 @@
         {
             initialize();
         }
-
+        if (repositories == null)
+        {
+            return resolver();
+        }
         return new ResolverImpl(m_context, repositories, m_logger);
     }
 
-    public synchronized Resource[] discoverResources(String filterExpr)
+    public synchronized Resource[] discoverResources(String filterExpr) throws InvalidSyntaxException
     {
         if (!m_initialized)
         {
             initialize();
         }
 
-        Filter filter = null;
-        try
-        {
-            filter = m_context.createFilter(filterExpr);
-        }
-        catch (InvalidSyntaxException ex)
-        {
-            m_logger.log(
-                Logger.LOG_WARNING,
-                "Error while discovering resources for " + filterExpr,
-                ex);
-            return new Resource[0];
-        }
-
-        Resource[] resources = null;
+        Filter filter = filterExpr != null ? filter(filterExpr) : null;
+        Resource[] resources;
         MapToDictionary dict = new MapToDictionary(null);
         Repository[] repos = listRepositories();
         List matchList = new ArrayList();
@@ -169,7 +157,7 @@
             for (int resIdx = 0; (resources != null) && (resIdx < resources.length); resIdx++)
             {
                 dict.setSourceMap(resources[resIdx].getProperties());
-                if (filter.match(dict))
+                if (filter == null || filter.match(dict))
                 {
                     matchList.add(resources[resIdx]);
                 }
@@ -206,8 +194,7 @@
                     Capability[] caps = resources[resIdx].getCapabilities();
                     for (int capIdx = 0; (caps != null) && (capIdx < caps.length); capIdx++)
                     {
-                        if (caps[capIdx].getName().equals(requirements[reqIdx].getName())
-                            && requirements[reqIdx].isSatisfied(caps[capIdx]))
+                        if (requirements[reqIdx].isSatisfied(caps[capIdx]))
                         {
                             reqMatch = true;
                             break;
@@ -253,6 +240,11 @@
         return new RepositoryImpl(null, url, 0, m_logger);
     }
 
+    public Repository repository(Resource[] resources) 
+    {
+        return new RepositoryImpl(resources);
+    }
+
     public Capability capability(String name, Map properties)
     {
         CapabilityImpl cap = new CapabilityImpl();
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
index a1635a9..53d414a 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RepositoryImpl.java
@@ -60,6 +60,15 @@
     // Reusable comparator for sorting resources by name.
     private ResourceComparator m_nameComparator = new ResourceComparator();
 
+    public RepositoryImpl(Resource[] resources)
+    {
+        m_repoAdmin = null;
+        m_url = null;
+        m_logger = null;
+        m_resources = resources;
+        m_lastmodified = System.currentTimeMillis();
+    }
+
     public RepositoryImpl(RepositoryAdminImpl repoAdmin, URL url, Logger logger)
         throws Exception
     {
@@ -167,11 +176,6 @@
         }
     }
 
-    public boolean isLocal()
-    {
-        return false;
-    }
-
     /**
      * Default setter method when setting parsed data from the XML file,
      * which currently ignores everything.
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
index 4ccc4da..cfafcac 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/RequirementImpl.java
@@ -20,12 +20,10 @@
 
 import org.apache.felix.bundlerepository.Capability;
 import org.apache.felix.bundlerepository.Requirement;
-import org.apache.felix.bundlerepository.Resource;
 import org.osgi.framework.InvalidSyntaxException;
 
 public class RequirementImpl implements Requirement
 {
-    private Resource m_resource;
     private String m_name = null;
     private boolean m_extend = false;
     private boolean m_multiple = false;
@@ -37,16 +35,6 @@
     {
     }
 
-    public Resource getResource()
-    {
-        return m_resource;
-    }
-
-    public void setResource(Resource resource)
-    {
-        m_resource = resource;
-    }
-
     public synchronized String getName()
     {
         return m_name;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
index 56bfad3..1bdb1da 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResolverImpl.java
@@ -33,13 +33,12 @@
     private final Set m_addedSet = new HashSet();
     private final Set m_addedRequirementSet = new HashSet();
     private final Set m_globalCapabilities = new HashSet();
-    private final Set m_globalRequirements = new HashSet();
     private final Set m_failedSet = new HashSet();
     private final Set m_resolveSet = new HashSet();
     private final Set m_requiredSet = new HashSet();
     private final Set m_optionalSet = new HashSet();
     private final Map m_reasonMap = new HashMap();
-    private final Map m_unsatisfiedMap = new HashMap();
+    private final Set m_unsatisfiedSet = new HashSet();
     private boolean m_resolved = false;
     private long m_resolveTimeStamp;
     private int m_resolutionFlags;
@@ -84,24 +83,11 @@
         return (Capability[]) m_globalCapabilities.toArray(new Capability[m_globalCapabilities.size()]);
     }
 
-    public void addGlobalRequirement(Requirement requirement)
-    {
-        m_resolved = false;
-        m_globalRequirements.add(requirement);
-    }
-
-    public Requirement[] getGlobalRequirements()
-    {
-        return (Requirement[]) m_globalRequirements.toArray(new Requirement[m_globalRequirements.size()]);
-    }
-
-    public synchronized Requirement[] getUnsatisfiedRequirements()
+    public synchronized Resource[] getRequiredResources()
     {
         if (m_resolved)
         {
-            return (Requirement[])
-                m_unsatisfiedMap.keySet().toArray(
-                    new Requirement[m_unsatisfiedMap.size()]);
+            return (Resource[]) m_requiredSet.toArray(new Resource[m_requiredSet.size()]);
         }
         throw new IllegalStateException("The resources have not been resolved.");
     }
@@ -110,38 +96,26 @@
     {
         if (m_resolved)
         {
-            return (Resource[])
-                m_optionalSet.toArray(
-                    new Resource[m_optionalSet.size()]);
+            return (Resource[]) m_optionalSet.toArray(new Resource[m_optionalSet.size()]);
         }
         throw new IllegalStateException("The resources have not been resolved.");
     }
 
-    public synchronized Requirement[] getReason(Resource resource)
+    public synchronized Reason[] getReason(Resource resource)
     {
         if (m_resolved)
         {
-            return (Requirement[]) m_reasonMap.get(resource);
+            List l = (List) m_reasonMap.get(resource);
+            return l != null ? (Reason[]) l.toArray(new Reason[l.size()]) : null;
         }
         throw new IllegalStateException("The resources have not been resolved.");
     }
 
-    public synchronized Resource[] getResources(Requirement requirement)
+    public synchronized Reason[] getUnsatisfiedRequirements()
     {
         if (m_resolved)
         {
-            return (Resource[]) m_unsatisfiedMap.get(requirement);
-        }
-        throw new IllegalStateException("The resources have not been resolved.");
-    }
-
-    public synchronized Resource[] getRequiredResources()
-    {
-        if (m_resolved)
-        {
-            return (Resource[])
-                m_requiredSet.toArray(
-                    new Resource[m_requiredSet.size()]);
+            return (Reason[]) m_unsatisfiedSet.toArray(new Reason[m_unsatisfiedSet.size()]);
         }
         throw new IllegalStateException("The resources have not been resolved.");
     }
@@ -151,17 +125,21 @@
         List resources = new ArrayList();
         for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
         {
-            if (m_repositories[repoIdx].isLocal() == local)
+            boolean isLocal = m_repositories[repoIdx] instanceof LocalRepositoryImpl;
+            boolean isSystem = m_repositories[repoIdx] instanceof SystemRepositoryImpl;
+            if (isLocal && (m_resolutionFlags & NO_LOCAL_RESOURCES) != 0) {
+                continue;
+            }
+            if (isSystem && (m_resolutionFlags & NO_SYSTEM_BUNDLE) != 0) {
+                continue;
+            }
+            Resource[] res = m_repositories[repoIdx].getResources();
+            for (int resIdx = 0; (res != null) && (resIdx < res.length); resIdx++)
             {
-                boolean isLocal = m_repositories[repoIdx] instanceof LocalRepositoryImpl;
-                boolean isSystem = m_repositories[repoIdx] instanceof SystemRepositoryImpl;
-                if (isLocal && (m_resolutionFlags & NO_LOCAL_RESOURCES) != 0) {
-                    continue;
+                if (res[resIdx].isLocal() == local)
+                {
+                    resources.add(res[resIdx]);
                 }
-                if (isSystem && (m_resolutionFlags & NO_SYSTEM_BUNDLE) != 0) {
-                    continue;
-                }
-                resources.addAll(Arrays.asList(m_repositories[repoIdx].getResources()));
             }
         }
         return (Resource[]) resources.toArray(new Resource[resources.size()]);
@@ -177,16 +155,12 @@
         // Find resources
         Resource[] locals = getResources(true);
         Resource[] remotes = getResources(false);
-        remotes = filter(remotes, (Requirement[]) m_globalRequirements.toArray(new Requirement[m_globalRequirements.size()]));
 
         // time of the resolution process start
         m_resolveTimeStamp = 0;
         for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
         {
-            if (m_repositories[repoIdx].isLocal())
-            {
-                m_resolveTimeStamp = Math.max(m_resolveTimeStamp, m_repositories[repoIdx].getLastModified());
-            }
+            m_resolveTimeStamp = Math.max(m_resolveTimeStamp, m_repositories[repoIdx].getLastModified());
         }
 
         // Reset instance values.
@@ -195,7 +169,7 @@
         m_requiredSet.clear();
         m_optionalSet.clear();
         m_reasonMap.clear();
-        m_unsatisfiedMap.clear();
+        m_unsatisfiedSet.clear();
         m_resolved = true;
         m_resolutionFlags = flags;
 
@@ -209,13 +183,11 @@
             {
                 Capability cap = (Capability) iter.next();
                 fake.addCapability(cap);
-                ((CapabilityImpl) cap).setResource(null);
             }
             for (Iterator iter = m_addedRequirementSet.iterator(); iter.hasNext();)
             {
                 Requirement req = (Requirement) iter.next();
                 fake.addRequire(req);
-                ((RequirementImpl) req).setResource(null);
             }
             if (!resolve(fake, locals, remotes, false))
             {
@@ -332,7 +304,7 @@
                     // can resolve.
                     while ((candidate == null) && !candidateCapabilities.isEmpty())
                     {
-                        Capability bestCapability = getBestCandidate(candidateCapabilities);
+                        ResourceCapability bestCapability = getBestCandidate(candidateCapabilities);
 
                         // Try to resolve the best resource.
                         if (resolve(bestCapability.getResource(), locals, remotes, optional || reqs[reqIdx].isOptional()))
@@ -351,20 +323,8 @@
                     // The resolve failed.
                     result = false;
                     // Associated the current resource to the requirement
-                    // in the unsatisfied requirement map.
-                    Resource[] resources = (Resource[]) m_unsatisfiedMap.get(reqs[reqIdx]);
-                    if (resources == null)
-                    {
-                        resources = new Resource[] { resource };
-                    }
-                    else
-                    {
-                        Resource[] tmp = new Resource[resources.length + 1];
-                        System.arraycopy(resources, 0, tmp, 0, resources.length);
-                        tmp[resources.length] = resource;
-                        resources = tmp;
-                    }
-                    m_unsatisfiedMap.put(reqs[reqIdx], resources);
+                    // in the unsatisfied requirement set.
+                    m_unsatisfiedSet.add(new ReasonImpl(resource, reqs[reqIdx]));
                 }
                 else if (candidate != null)
                 {
@@ -387,7 +347,13 @@
                         }
 
                         // Add the reason why the candidate was selected.
-                        addReason(candidate, reqs[reqIdx]);
+                        List reasons = (List) m_reasonMap.get(candidate);
+                        if (reasons == null)
+                        {
+                            reasons = new ArrayList();
+                            m_reasonMap.put(candidate, reasons);
+                        }
+                        reasons.add(new ReasonImpl(resource, reqs[reqIdx]));
                     }
                     else
                     {
@@ -450,7 +416,7 @@
                 {
                     if (req.isSatisfied(caps[capIdx]))
                     {
-                        matchingCapabilities.add(caps[capIdx]);
+                        matchingCapabilities.add(new ResourceCapabilityImpl(resources[resIdx], caps[capIdx]));
                     }
                 }
             }
@@ -467,22 +433,22 @@
      * @param caps
      * @return
      */
-    private Capability getBestCandidate(List caps)
+    private ResourceCapability getBestCandidate(List caps)
     {
         Version bestVersion = null;
-        Capability best = null;
+        ResourceCapability best = null;
         boolean bestLocal = false;
 
         for(int capIdx = 0; capIdx < caps.size(); capIdx++)
         {
-            Capability current = (Capability) caps.get(capIdx);
-            boolean isCurrentLocal = current.getResource().getRepository() == null;
+            ResourceCapability current = (ResourceCapability) caps.get(capIdx);
+            boolean isCurrentLocal = current.getResource().isLocal();
 
             if (best == null)
             {
                 best = current;
                 bestLocal = isCurrentLocal;
-                Object v = current.getProperties().get(Resource.VERSION);
+                Object v = current.getCapability().getProperties().get(Resource.VERSION);
                 if ((v != null) && (v instanceof Version))
                 {
                     bestVersion = (Version) v;
@@ -490,7 +456,7 @@
             }
             else if ((m_resolutionFlags & DO_NOT_PREFER_LOCAL) != 0 || !bestLocal || isCurrentLocal)
             {
-                Object v = current.getProperties().get(Resource.VERSION);
+                Object v = current.getCapability().getProperties().get(Resource.VERSION);
 
                 // If there is no version, then select the resource
                 // with the greatest number of capabilities.
@@ -538,11 +504,6 @@
         }
     }
 
-    public synchronized void deploy(boolean start)
-    {
-        deploy(START);
-    }
-
     public synchronized void deploy(int flags)
     {
         m_deployFlags = flags;
@@ -560,8 +521,7 @@
         // to see if the local state changes overlap with the resolver.
         for (int repoIdx = 0; (m_repositories != null) && (repoIdx < m_repositories.length); repoIdx++)
         {
-            if (m_repositories[repoIdx].isLocal()
-                    && m_repositories[repoIdx].getLastModified() > m_resolveTimeStamp)
+            if (m_repositories[repoIdx].getLastModified() > m_resolveTimeStamp)
             {
                 throw new IllegalStateException("Framework state has changed, must resolve again.");
             }
@@ -716,23 +676,6 @@
         return bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null;
     }
     
-    private void addReason(Resource resource, Requirement req)
-    {
-        Requirement[] reasons = (Requirement[]) m_reasonMap.get(resource);
-        if (reasons == null)
-        {
-            reasons = new Requirement[] { req };
-        }
-        else
-        {
-            Requirement[] tmp = new Requirement[reasons.length + 1];
-            System.arraycopy(reasons, 0, tmp, 0, reasons.length);
-            tmp[reasons.length] = req;
-            reasons = tmp;
-        }
-        m_reasonMap.put(resource, reasons);
-    }
-
     // TODO: OBR - Think about this again and make sure that deployment ordering
     // won't impact it...we need to update the local state too.
     private LocalResourceImpl findUpdatableLocalResource(Resource resource)
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapability.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapability.java
new file mode 100644
index 0000000..64ea01f
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapability.java
@@ -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.bundlerepository.impl;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Resource;
+
+public interface ResourceCapability
+{
+
+    Resource getResource();
+
+    Capability getCapability();
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapabilityImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapabilityImpl.java
new file mode 100644
index 0000000..45cd72e
--- /dev/null
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceCapabilityImpl.java
@@ -0,0 +1,46 @@
+/*
+ * 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.bundlerepository.impl;
+
+import org.apache.felix.bundlerepository.Capability;
+import org.apache.felix.bundlerepository.Resource;
+
+
+public class ResourceCapabilityImpl implements ResourceCapability
+{
+    private final Resource resource;
+    private final Capability capability;
+
+    public ResourceCapabilityImpl(Resource resource, Capability capability)
+    {
+        this.resource = resource;
+        this.capability = capability;
+    }
+
+    public Resource getResource()
+    {
+        return resource;
+    }
+
+    public Capability getCapability()
+    {
+        return capability;
+    }
+
+}
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
index 10f99ab..75f33d6 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/ResourceImpl.java
@@ -32,7 +32,7 @@
 {
 
     private final Map m_map = new HashMap();
-    private RepositoryImpl m_repo = null;
+    private Repository m_repo;
     private List m_capList = new ArrayList();
     private List m_reqList = new ArrayList();
 
@@ -90,6 +90,14 @@
         return m_hash;
     }
 
+    public Repository getRepository() {
+        return m_repo;
+    }
+
+    public void setRepository(Repository repository) {
+        this.m_repo = repository;
+    }
+
     public Map getProperties()
     {
         if (!m_converted)
@@ -137,7 +145,6 @@
 
     protected void addRequire(Requirement req)
     {
-        ((RequirementImpl) req).setResource(this);
         m_reqList.add(req);
     }
 
@@ -148,7 +155,6 @@
 
     protected void addCapability(Capability cap)
     {
-        ((CapabilityImpl) cap).setResource(this);
         m_capList.add(cap);
     }
 
@@ -173,14 +179,9 @@
         catList.add(cat.getId());
     }
 
-    public Repository getRepository()
+    public boolean isLocal()
     {
-        return m_repo;
-    }
-
-    protected void setRepository(RepositoryImpl repo)
-    {
-        m_repo = repo;
+        return false;
     }
 
     /**
@@ -207,7 +208,7 @@
         {
             m_sourceURI = (String) value;
         }
-        else if (key.equals(JAVADOC))
+        else if (key.equals(JAVADOC_URL))
         {
             m_javadocURI = (String) value;
         }
@@ -268,7 +269,7 @@
                 }
                 if (m_javadocURI != null)
                 {
-                    m_map.put(JAVADOC, new URL(base, m_javadocURI));
+                    m_map.put(JAVADOC_URL, new URL(base, m_javadocURI));
                 }
                 m_converted = true;
             }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
index 1bca652..05a9e5a 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/SystemRepositoryImpl.java
@@ -69,9 +69,4 @@
         return lastModified;
     }
 
-    public boolean isLocal()
-    {
-        return true;
-    }
-
 }
\ No newline at end of file
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
index 0699555..f2dac89 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/CapabilityWrapper.java
@@ -1,3 +1,21 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
 import java.util.Map;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryAdminWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryAdminWrapper.java
index 27599f0..9c6379c 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryAdminWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryAdminWrapper.java
@@ -1,8 +1,27 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
 import java.net.URL;
 
 import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.osgi.framework.InvalidSyntaxException;
 
 public class RepositoryAdminWrapper implements org.osgi.service.obr.RepositoryAdmin
 {
@@ -15,7 +34,11 @@
     }
 
     public org.osgi.service.obr.Resource[] discoverResources(String filterExpr) {
-        return Wrapper.wrap(admin.discoverResources(filterExpr));
+        try {
+            return Wrapper.wrap(admin.discoverResources(filterExpr));
+        } catch (InvalidSyntaxException e) {
+            throw new RuntimeException(e);
+        }
     }
 
     public org.osgi.service.obr.Resolver resolver() {
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryWrapper.java
index a7dd140..cb1dff7 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RepositoryWrapper.java
@@ -1,17 +1,27 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
 import java.net.URL;
 
 import org.apache.felix.bundlerepository.Repository;
-import org.apache.felix.bundlerepository.Resource;
 
-/**
- * Created by IntelliJ IDEA.
- * User: gnodet
- * Date: Feb 25, 2010
- * Time: 11:50:21 PM
- * To change this template use File | Settings | File Templates.
- */
 public class RepositoryWrapper implements org.osgi.service.obr.Repository {
 
     private final Repository repository;
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RequirementWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RequirementWrapper.java
index 06057db..c9008b4 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RequirementWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/RequirementWrapper.java
@@ -1,15 +1,25 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
-import org.apache.felix.bundlerepository.Capability;
 import org.apache.felix.bundlerepository.Requirement;
 
-/**
- * Created by IntelliJ IDEA.
- * User: gnodet
- * Date: Feb 25, 2010
- * Time: 11:47:36 PM
- * To change this template use File | Settings | File Templates.
- */
 public class RequirementWrapper implements org.osgi.service.obr.Requirement {
 
     final Requirement requirement;
@@ -45,4 +55,19 @@
     public boolean isSatisfied(org.osgi.service.obr.Capability capability) {
         return requirement.isSatisfied(Wrapper.unwrap(capability));
     }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RequirementWrapper that = (RequirementWrapper) o;
+
+        if (requirement != null ? !requirement.equals(that.requirement) : that.requirement != null) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        return requirement != null ? requirement.hashCode() : 0;
+    }
 }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResolverWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResolverWrapper.java
index af55277..5308e02 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResolverWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResolverWrapper.java
@@ -1,16 +1,32 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.bundlerepository.Reason;
 import org.apache.felix.bundlerepository.Requirement;
 import org.apache.felix.bundlerepository.Resolver;
-import org.apache.felix.bundlerepository.Resource;
 
-/**
- * Created by IntelliJ IDEA.
- * User: gnodet
- * Date: Feb 25, 2010
- * Time: 11:52:08 PM
- * To change this template use File | Settings | File Templates.
- */
 public class ResolverWrapper implements org.osgi.service.obr.Resolver {
 
     private final Resolver resolver;
@@ -28,8 +44,8 @@
         return Wrapper.wrap(resolver.getAddedResources());
     }
 
-    public org.osgi.service.obr.Requirement[] getUnsatisfiedRequirements() {
-        return Wrapper.wrap(resolver.getUnsatisfiedRequirements());
+    public org.osgi.service.obr.Resource[] getRequiredResources() {
+        return Wrapper.wrap(resolver.getRequiredResources());
     }
 
     public org.osgi.service.obr.Resource[] getOptionalResources() {
@@ -37,15 +53,32 @@
     }
 
     public org.osgi.service.obr.Requirement[] getReason(org.osgi.service.obr.Resource resource) {
-        return Wrapper.wrap(resolver.getReason(Wrapper.unwrap(resource)));
+        Reason[] r = resolver.getReason(Wrapper.unwrap(resource));
+        if (r == null)
+        {
+            return null;
+        }
+        Requirement[] r2 = new Requirement[r.length];
+        for (int reaIdx = 0; reaIdx < r.length; reaIdx++)
+        {
+            r2[reaIdx] = r[reaIdx].getRequirement();
+        }
+        return Wrapper.wrap(r2);
+    }
+
+    public org.osgi.service.obr.Requirement[] getUnsatisfiedRequirements() {
+        Map map = getUnsatisfiedRequirementsMap();
+        return (org.osgi.service.obr.Requirement[]) map.keySet().toArray(new org.osgi.service.obr.Requirement[map.size()]);
     }
 
     public org.osgi.service.obr.Resource[] getResources(org.osgi.service.obr.Requirement requirement) {
-        return Wrapper.wrap(resolver.getResources(Wrapper.unwrap(requirement)));
-    }
-
-    public org.osgi.service.obr.Resource[] getRequiredResources() {
-        return Wrapper.wrap(resolver.getRequiredResources());
+        Map map = getUnsatisfiedRequirementsMap();
+        List l = (List) map.get(requirement);
+        if (l == null)
+        {
+            return null;
+        }
+        return (org.osgi.service.obr.Resource[]) l.toArray(new org.osgi.service.obr.Resource[l.size()]);
     }
 
     public boolean resolve() {
@@ -53,6 +86,24 @@
     }
 
     public void deploy(boolean start) {
-        resolver.deploy(start);
+        resolver.deploy(start ? Resolver.START : 0);
+    }
+
+    private Map getUnsatisfiedRequirementsMap() {
+        Reason[] reasons = resolver.getUnsatisfiedRequirements();
+        Map map = new HashMap();
+        for (int i = 0; i < reasons.length; i++)
+        {
+            org.osgi.service.obr.Requirement req = Wrapper.wrap(reasons[i].getRequirement());
+            org.osgi.service.obr.Resource res = Wrapper.wrap(reasons[i].getResource());
+            List l = (List) map.get(req);
+            if (l == null)
+            {
+                l = new ArrayList();
+                map.put(req, l);
+            }
+            l.add(res);
+        }
+        return map;
     }
 }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResourceWrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResourceWrapper.java
index f7b8856..0dd0184 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResourceWrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/ResourceWrapper.java
@@ -1,3 +1,21 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
 import java.net.URL;
@@ -54,6 +72,6 @@
     }
 
     public Repository getRepository() {
-        return Wrapper.wrap(resource.getRepository());
+        throw new UnsupportedOperationException();
     }
 }
diff --git a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/Wrapper.java b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/Wrapper.java
index df132c3..d590882 100644
--- a/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/Wrapper.java
+++ b/bundlerepository/src/main/java/org/apache/felix/bundlerepository/impl/wrapper/Wrapper.java
@@ -1,3 +1,21 @@
+/*
+ * 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.bundlerepository.impl.wrapper;
 
 import org.apache.felix.bundlerepository.Capability;
diff --git a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
index 50836bb..6facb80 100644
--- a/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
+++ b/bundlerepository/src/test/java/org/apache/felix/bundlerepository/impl/RepositoryImplTest.java
@@ -57,11 +57,11 @@
 
         // first resource is from the referral1_repository.xml
         assertEquals("6", res[0].getId());
-        assertEquals("referral1_repository", res[0].getRepository().getName());
+//        assertEquals("referral1_repository", res[0].getRepository().getName());
 
         // second resource is from the referred.xml
         assertEquals("99", res[1].getId());
-        assertEquals("referred", res[1].getRepository().getName());
+//        assertEquals("referred", res[1].getRepository().getName());
     }
 
     public void testReferral2() throws Exception
@@ -86,7 +86,7 @@
 
         // first resource is from the referral1_repository.xml
         assertEquals("6", res[0].getId());
-        assertEquals("referral1_repository", res[0].getRepository().getName());
+//        assertEquals("referral1_repository", res[0].getRepository().getName());
     }
 
     private RepositoryAdminImpl createRepositoryAdmin() throws Exception