You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2010/07/02 12:18:34 UTC

svn commit: r959937 - in /karaf/trunk: ./ assembly/ assembly/src/main/filtered-resources/ features/ features/core/src/main/java/org/apache/karaf/features/ features/core/src/main/java/org/apache/karaf/features/internal/ features/core/src/main/resources/...

Author: gnodet
Date: Fri Jul  2 10:18:32 2010
New Revision: 959937

URL: http://svn.apache.org/viewvc?rev=959937&view=rev
Log:
KARAF-31: Use OBR as a possible way to resolve transitive dependencies of features

Added:
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Resolver.java
      - copied, changed from r959895, karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java
    karaf/trunk/features/obr/
    karaf/trunk/features/obr/pom.xml
    karaf/trunk/features/obr/src/
    karaf/trunk/features/obr/src/main/
    karaf/trunk/features/obr/src/main/java/
    karaf/trunk/features/obr/src/main/java/org/
    karaf/trunk/features/obr/src/main/java/org/apache/
    karaf/trunk/features/obr/src/main/java/org/apache/karaf/
    karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/
    karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/
    karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/
    karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/ObrResolver.java
    karaf/trunk/features/obr/src/main/resources/
    karaf/trunk/features/obr/src/main/resources/OSGI-INF/
    karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/
    karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/features-obr.xml
    karaf/trunk/features/obr/src/test/
    karaf/trunk/features/obr/src/test/java/
    karaf/trunk/features/obr/src/test/java/org/
    karaf/trunk/features/obr/src/test/java/org/apache/
    karaf/trunk/features/obr/src/test/java/org/apache/karaf/
    karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/
    karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/
    karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/
    karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/ObrResolverTest.java
Modified:
    karaf/trunk/assembly/pom.xml
    karaf/trunk/assembly/src/main/filtered-resources/features.xml
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
    karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
    karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/gshell-features.xml
    karaf/trunk/features/pom.xml
    karaf/trunk/pom.xml
    karaf/trunk/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java

Modified: karaf/trunk/assembly/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/assembly/pom.xml?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/assembly/pom.xml (original)
+++ karaf/trunk/assembly/pom.xml Fri Jul  2 10:18:32 2010
@@ -88,6 +88,10 @@
             <artifactId>org.apache.karaf.features.management</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.obr</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf.admin</groupId>
             <artifactId>org.apache.karaf.admin.core</artifactId>
         </dependency>

Modified: karaf/trunk/assembly/src/main/filtered-resources/features.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/assembly/src/main/filtered-resources/features.xml?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/assembly/src/main/filtered-resources/features.xml (original)
+++ karaf/trunk/assembly/src/main/filtered-resources/features.xml Fri Jul  2 10:18:32 2010
@@ -50,6 +50,7 @@
     <feature name="obr" version="${project.version}">
         <bundle>mvn:org.apache.felix/org.apache.felix.bundlerepository/${felix.bundlerepository.version}</bundle>
         <bundle>mvn:org.apache.karaf.shell/org.apache.karaf.shell.obr/${project.version}</bundle>
+        <bundle>mvn:org.apache.karaf.features/org.apache.karaf.features.obr/${project.version}</bundle>
     </feature>
     <feature name="http" version="${project.version}">
         <config name="org.ops4j.pax.web">

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java Fri Jul  2 10:18:32 2010
@@ -30,6 +30,8 @@ public interface Feature {
 
     String getVersion();
 
+    String getResolver();
+
     List<Feature> getDependencies();
 
     List<String> getBundles();

Copied: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Resolver.java (from r959895, karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java)
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Resolver.java?p2=karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Resolver.java&p1=karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java&r1=959895&r2=959937&rev=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Feature.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/Resolver.java Fri Jul  2 10:18:32 2010
@@ -17,23 +17,9 @@
 package org.apache.karaf.features;
 
 import java.util.List;
-import java.util.Map;
 
-/**
- * A feature is a list of bundles associated identified by its name.
- */
-public interface Feature {
+public interface Resolver {
 
-    String getId();
-
-    String getName();
-
-    String getVersion();
-
-    List<Feature> getDependencies();
-
-    List<String> getBundles();
-
-    Map<String, Map<String, String>> getConfigurations();
+    List<String> resolve(Feature feature) throws Exception;
 
 }

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeatureImpl.java Fri Jul  2 10:18:32 2010
@@ -31,12 +31,16 @@ public class FeatureImpl implements Feat
     private String id;
     private String name;
     private String version;
+    private String resolver;
     private List<Feature> dependencies = new ArrayList<Feature>();
     private List<String> bundles = new ArrayList<String>();
     private Map<String, Map<String,String>> configs = new HashMap<String, Map<String,String>>();
     public static String SPLIT_FOR_NAME_AND_VERSION = "_split_for_name_and_version_";
     public static String DEFAULT_VERSION = "0.0.0";
-    
+
+    public FeatureImpl() {
+    }
+
     public FeatureImpl(String name) {
         this(name, DEFAULT_VERSION);
     }
@@ -63,6 +67,14 @@ public class FeatureImpl implements Feat
 		this.version = version;
 	}
 
+    public String getResolver() {
+        return resolver;
+    }
+
+    public void setResolver(String resolver) {
+        this.resolver = resolver;
+    }
+
     public List<Feature> getDependencies() {
         return dependencies;
     }

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/FeaturesServiceImpl.java Fri Jul  2 10:18:32 2010
@@ -38,10 +38,12 @@ import org.apache.karaf.features.Reposit
 import org.apache.felix.utils.manifest.Clause;
 import org.apache.felix.utils.manifest.Parser;
 import org.apache.felix.utils.version.VersionRange;
+import org.apache.karaf.features.Resolver;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleException;
 import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
 import org.osgi.service.cm.Configuration;
@@ -51,6 +53,7 @@ import org.osgi.service.prefs.BackingSto
 import org.osgi.service.prefs.Preferences;
 import org.osgi.service.prefs.PreferencesService;
 import org.osgi.service.startlevel.StartLevel;
+import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.helpers.MessageFormatter;
@@ -74,6 +77,7 @@ public class FeaturesServiceImpl impleme
     private ConfigurationAdmin configAdmin;
     private PackageAdmin packageAdmin;
     private StartLevel startLevel;
+    private long resolverTimeout = 5000;
     private PreferencesService preferences;
     private Set<URI> uris;
     private Map<URI, RepositoryImpl> repositories = new HashMap<URI, RepositoryImpl>();
@@ -124,6 +128,14 @@ public class FeaturesServiceImpl impleme
         this.startLevel = startLevel;
     }
 
+    public long getResolverTimeout() {
+        return resolverTimeout;
+    }
+
+    public void setResolverTimeout(long resolverTimeout) {
+        this.resolverTimeout = resolverTimeout;
+    }
+
     public void registerListener(FeaturesListener listener) {
         listeners.add(listener);
         for (Repository repository : listRepositories()) {
@@ -385,13 +397,31 @@ public class FeaturesServiceImpl impleme
             }
         }
         Set<Long> bundles = new TreeSet<Long>();
-        for (String bundleLocation : feature.getBundles()) {
+        for (String bundleLocation : resolve(feature)) {
             Bundle b = installBundleIfNeeded(state, bundleLocation);
             bundles.add(b.getBundleId());
         }
         state.features.put(feature, bundles);
     }
 
+    protected List<String> resolve(Feature feature) throws Exception {
+        String resolver = feature.getResolver();
+        // If no resolver is specified, we expect a list of uris
+        if (resolver == null || resolver.length() == 0) {
+            return feature.getBundles();
+        }
+        // Else, find the resolver
+        String filter = "(&(" + Constants.OBJECTCLASS + "=" + Resolver.class.getName() + ")(name=" + resolver + "))";
+        ServiceTracker tracker = new ServiceTracker(bundleContext, FrameworkUtil.createFilter(filter), null);
+        tracker.open();
+        try {
+            Resolver r = (Resolver) tracker.waitForService(resolverTimeout);
+            return r.resolve(feature);
+        } finally {
+            tracker.close();
+        }
+    }
+
     protected Set<Bundle> findBundlesToRefresh(InstallationState state) {
         Set<Bundle> bundles = new HashSet<Bundle>();
         bundles.addAll(findBundlesWithOptionalPackagesToRefresh(state));

Modified: karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java (original)
+++ karaf/trunk/features/core/src/main/java/org/apache/karaf/features/internal/RepositoryImpl.java Fri Jul  2 10:18:32 2010
@@ -127,6 +127,11 @@ public class RepositoryImpl implements R
                         f = new FeatureImpl(name);
                     }
 
+                    String resolver = e.getAttribute("resolver");
+                    if (resolver != null && resolver.length() > 0) {
+                        f.setResolver(resolver);
+                    }
+
                     NodeList featureNodes = e.getElementsByTagName("feature");
                     for (int j = 0; j < featureNodes.getLength(); j++) {
                         Element b = (Element) featureNodes.item(j);

Modified: karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/gshell-features.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/gshell-features.xml?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/gshell-features.xml (original)
+++ karaf/trunk/features/core/src/main/resources/OSGI-INF/blueprint/gshell-features.xml Fri Jul  2 10:18:32 2010
@@ -26,6 +26,7 @@
         <ext:default-properties>
             <ext:property name="featuresRepositories" value=""/>
             <ext:property name="featuresBoot" value=""/>
+            <ext:property name="resolverTimeout" value="5000"/>
         </ext:default-properties>
         <ext:location>file:$(karaf.base)/etc/org.apache.karaf.features.cfg</ext:location>
     </ext:property-placeholder>
@@ -33,6 +34,7 @@
     <bean id="featuresService" class="org.apache.karaf.features.internal.FeaturesServiceImpl" init-method="start" destroy-method="stop">
         <property name="urls" value="$[featuresRepositories]" />
         <property name="boot" value="$[featuresBoot]" />
+        <property name="resolverTimeout" value="$[resolverTimeout]" />
         <property name="configAdmin" ref="configAdmin" />
         <property name="packageAdmin" ref="packageAdmin" />
         <property name="preferences" ref="preferences" />

Added: karaf/trunk/features/obr/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/features/obr/pom.xml?rev=959937&view=auto
==============================================================================
--- karaf/trunk/features/obr/pom.xml (added)
+++ karaf/trunk/features/obr/pom.xml Fri Jul  2 10:18:32 2010
@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.features</groupId>
+        <artifactId>features</artifactId>
+        <version>1.99.0-SNAPSHOT</version>
+    </parent>
+
+    <groupId>org.apache.karaf.features</groupId>
+    <artifactId>org.apache.karaf.features.obr</artifactId>
+    <packaging>bundle</packaging>
+    <version>1.99.0-SNAPSHOT</version>
+    <name>Apache Karaf :: Features OBR Resolver</name>
+
+    <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.bundlerepository</artifactId>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Export-Package>
+                            ${project.artifactId}*;version=${project.version}
+                        </Export-Package>
+                        <Import-Package>
+                            !${project.artifactId}*,
+                            *
+                        </Import-Package>
+                        <Private-Package>org.apache.karaf.features.obr.internal</Private-Package>
+                        <_versionpolicy>${bnd.version.policy}</_versionpolicy>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

Added: karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/ObrResolver.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/ObrResolver.java?rev=959937&view=auto
==============================================================================
--- karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/ObrResolver.java (added)
+++ karaf/trunk/features/obr/src/main/java/org/apache/karaf/features/obr/internal/ObrResolver.java Fri Jul  2 10:18:32 2010
@@ -0,0 +1,130 @@
+/*
+ * 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.karaf.features.obr.internal;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.bundlerepository.Reason;
+import org.apache.felix.bundlerepository.Repository;
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.Resolver;
+import org.osgi.framework.InvalidSyntaxException;
+
+public class ObrResolver implements Resolver {
+
+    private RepositoryAdmin repositoryAdmin;
+
+    public RepositoryAdmin getRepositoryAdmin() {
+        return repositoryAdmin;
+    }
+
+    public void setRepositoryAdmin(RepositoryAdmin repositoryAdmin) {
+        this.repositoryAdmin = repositoryAdmin;
+    }
+
+    public List<String> resolve(Feature feature) throws Exception {
+        List<Requirement> reqs = new ArrayList<Requirement>();
+        List<Resource> ress = new ArrayList<Resource>();
+        for (String bundleUrl : feature.getBundles()) {
+            try {
+                URL url = new URL(bundleUrl);
+                ress.add(repositoryAdmin.getHelper().createResource(url));
+            } catch (MalformedURLException e) {
+                reqs.add(parseRequirement(bundleUrl));
+            }
+        }
+
+        Repository repository = repositoryAdmin.getHelper().repository(ress.toArray(new Resource[ress.size()]));
+        List<Repository> repos = new ArrayList<Repository>();
+        repos.add(repositoryAdmin.getSystemRepository());
+        repos.add(repositoryAdmin.getLocalRepository());
+        repos.add(repository);
+        repos.addAll(Arrays.asList(repositoryAdmin.listRepositories()));
+        org.apache.felix.bundlerepository.Resolver resolver = repositoryAdmin.resolver(repos.toArray(new Repository[repos.size()]));
+
+        for (Resource res : ress) {
+            resolver.add(res);
+        }
+        for (Requirement req : reqs) {
+            resolver.add(req);
+        }
+
+        if (!resolver.resolve(org.apache.felix.bundlerepository.Resolver.NO_OPTIONAL_RESOURCES)) {
+            StringWriter w = new StringWriter();
+            PrintWriter out = new PrintWriter(w);
+            Reason[] failedReqs = resolver.getUnsatisfiedRequirements();
+            if ((failedReqs != null) && (failedReqs.length > 0)) {
+                out.println("Unsatisfied requirement(s):");
+                printUnderline(out, 27);
+                for (Reason r : failedReqs) {
+                    out.println("   " + r.getRequirement().getName() + ":" + r.getRequirement().getFilter());
+                    out.println("      " + r.getResource().getPresentationName());
+                }
+            } else {
+                out.println("Could not resolve targets.");
+            }
+            out.flush();
+            throw new Exception("Can not resolve feature:\n" + w.toString());
+        }
+
+        List<String> urls = new ArrayList<String>();
+        for (Resource res : resolver.getRequiredResources()) {
+            urls.add(res.getURI());
+        }
+        return urls;
+    }
+
+    protected void printUnderline(PrintWriter out, int length) {
+        for (int i = 0; i < length; i++) {
+            out.print('-');
+        }
+        out.println("");
+    }
+
+    protected Requirement parseRequirement(String req) throws InvalidSyntaxException {
+        int p = req.indexOf(':');
+        String name;
+        String filter;
+        if (p > 0) {
+            name = req.substring(0, p);
+            filter = req.substring(p + 1);
+        } else {
+            if (req.contains("package")) {
+                name = "package";
+            } else if (req.contains("service")) {
+                name = "service";
+            } else {
+                name = "bundle";
+            }
+            filter = req;
+        }
+        if (!filter.startsWith("(")) {
+            filter = "(" + filter + ")";
+        }
+        return repositoryAdmin.getHelper().requirement(name, filter);
+    }
+
+}

Added: karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/features-obr.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/features-obr.xml?rev=959937&view=auto
==============================================================================
--- karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/features-obr.xml (added)
+++ karaf/trunk/features/obr/src/main/resources/OSGI-INF/blueprint/features-obr.xml Fri Jul  2 10:18:32 2010
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+    <bean id="obrResolver" class="org.apache.karaf.features.obr.internal.ObrResolver">
+        <property name="repositoryAdmin" ref="repositoryAdmin" />
+    </bean>
+
+    <reference id="repositoryAdmin" interface="org.apache.felix.bundlerepository.RepositoryAdmin" />
+
+    <service ref="obrResolver" interface="org.apache.karaf.features.Resolver">
+        <service-properties>
+            <entry key="name" value="obr" />
+        </service-properties>
+    </service>
+
+</blueprint>

Added: karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/ObrResolverTest.java
URL: http://svn.apache.org/viewvc/karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/ObrResolverTest.java?rev=959937&view=auto
==============================================================================
--- karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/ObrResolverTest.java (added)
+++ karaf/trunk/features/obr/src/test/java/org/apache/karaf/features/obr/internal/ObrResolverTest.java Fri Jul  2 10:18:32 2010
@@ -0,0 +1,74 @@
+/*
+ * 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.karaf.features.obr.internal;
+
+import java.util.List;
+
+import org.apache.felix.bundlerepository.RepositoryAdmin;
+import org.apache.felix.bundlerepository.Requirement;
+import org.apache.felix.bundlerepository.Resolver;
+import org.apache.felix.bundlerepository.Resource;
+import org.apache.felix.bundlerepository.impl.DataModelHelperImpl;
+import org.apache.karaf.features.internal.FeatureImpl;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class ObrResolverTest {
+
+    @Test
+    public void testResolver() throws Exception {
+        String requirement = "bundle:(&(symbolicname=org.apache.camel.camel-blueprint)(version>=2.4.0)(version<2.4.1))";
+
+        FeatureImpl f = new FeatureImpl("f1", "1.0");
+        f.setResolver("obr");
+        f.addBundle(requirement);
+        RepositoryAdmin admin = createMock(RepositoryAdmin.class);
+        Resolver resolver = createMock(Resolver.class);
+        Resource resource = createMock(Resource.class);
+        ObrResolver obrResolver = new ObrResolver();
+        obrResolver.setRepositoryAdmin(admin);
+
+        Capture<Requirement> captureReq = new Capture<Requirement>();
+
+        expect(admin.getHelper()).andReturn(new DataModelHelperImpl()).anyTimes();
+        expect(admin.getSystemRepository()).andReturn(createMock(org.apache.felix.bundlerepository.Repository.class));
+        expect(admin.getLocalRepository()).andReturn(createMock(org.apache.felix.bundlerepository.Repository.class));
+        expect(admin.listRepositories()).andReturn(new org.apache.felix.bundlerepository.Repository[0]);
+        expect(admin.resolver(EasyMock.<org.apache.felix.bundlerepository.Repository[]>anyObject())).andReturn(resolver);
+        resolver.add(EasyMock.capture(captureReq));
+        expect(resolver.resolve(Resolver.NO_OPTIONAL_RESOURCES)).andReturn(true);
+        expect(resolver.getRequiredResources()).andReturn(new Resource[] { resource });
+        expect(resource.getURI()).andReturn("foo:bar");
+        replay(admin, resolver, resource);
+
+        List<String> bundles = obrResolver.resolve(f);
+        assertNotNull(bundles);
+        assertEquals(1, bundles.size());
+        assertEquals("foo:bar", bundles.get(0));
+        assertEquals(obrResolver.parseRequirement(requirement).toString(), captureReq.getValue().toString());
+        verify(admin, resolver, resource);
+    }
+
+}

Modified: karaf/trunk/features/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/features/pom.xml?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/features/pom.xml (original)
+++ karaf/trunk/features/pom.xml Fri Jul  2 10:18:32 2010
@@ -36,6 +36,7 @@
         <module>core</module>
         <module>command</module>
         <module>management</module>
+        <module>obr</module>
     </modules>
 
 </project>

Modified: karaf/trunk/pom.xml
URL: http://svn.apache.org/viewvc/karaf/trunk/pom.xml?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/pom.xml (original)
+++ karaf/trunk/pom.xml Fri Jul  2 10:18:32 2010
@@ -225,6 +225,11 @@
                 <version>${project.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.karaf.features</groupId>
+                <artifactId>org.apache.karaf.features.obr</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.apache.karaf.admin</groupId>
                 <artifactId>org.apache.karaf.admin.core</artifactId>
                 <version>${project.version}</version>

Modified: karaf/trunk/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java
URL: http://svn.apache.org/viewvc/karaf/trunk/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java?rev=959937&r1=959936&r2=959937&view=diff
==============================================================================
--- karaf/trunk/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java (original)
+++ karaf/trunk/webconsole/features/src/main/java/org/apache/karaf/webconsole/features/ExtendedFeature.java Fri Jul  2 10:18:32 2010
@@ -99,6 +99,10 @@ public class ExtendedFeature implements 
         return this.feature.getVersion();
     }
 
+    public String getResolver()
+    {
+        return this.feature.getResolver();
+    }
 
     //
     // Additional methods