You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ge...@apache.org on 2010/03/04 13:19:23 UTC

svn commit: r918963 - in /felix/trunk/karaf: ./ assembly/src/main/descriptors/ assembly/src/main/filtered-resources/etc/ commons/ commons/src/ commons/src/main/ commons/src/main/java/ commons/src/main/java/org/ commons/src/main/java/org/apache/ commons...

Author: gertv
Date: Thu Mar  4 12:19:22 2010
New Revision: 918963

URL: http://svn.apache.org/viewvc?rev=918963&view=rev
Log:
FELIX-2169: Improve dev:show-tree performance and avoid NPE when no matching export is found

Added:
    felix/trunk/karaf/commons/   (with props)
    felix/trunk/karaf/commons/pom.xml
    felix/trunk/karaf/commons/src/
    felix/trunk/karaf/commons/src/main/
    felix/trunk/karaf/commons/src/main/java/
    felix/trunk/karaf/commons/src/main/java/org/
    felix/trunk/karaf/commons/src/main/java/org/apache/
    felix/trunk/karaf/commons/src/main/java/org/apache/felix/
    felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/
    felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/
    felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/
    felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/VersionRange.java
      - copied, changed from r918911, felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/VersionRange.java
    felix/trunk/karaf/commons/src/test/
    felix/trunk/karaf/commons/src/test/java/
Removed:
    felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/VersionRange.java
Modified:
    felix/trunk/karaf/assembly/src/main/descriptors/unix-bin.xml
    felix/trunk/karaf/assembly/src/main/descriptors/windows-bin.xml
    felix/trunk/karaf/assembly/src/main/filtered-resources/etc/startup.properties
    felix/trunk/karaf/deployer/war/   (props changed)
    felix/trunk/karaf/features/core/pom.xml
    felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/FeaturesServiceImpl.java
    felix/trunk/karaf/pom.xml
    felix/trunk/karaf/shell/dev/pom.xml
    felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/ShowBundleTree.java
    felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Import.java
    felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Node.java
    felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/ImportTest.java
    felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/TreeTest.java
    felix/trunk/karaf/tooling/testing/   (props changed)

Modified: felix/trunk/karaf/assembly/src/main/descriptors/unix-bin.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/descriptors/unix-bin.xml?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/descriptors/unix-bin.xml (original)
+++ felix/trunk/karaf/assembly/src/main/descriptors/unix-bin.xml Thu Mar  4 12:19:22 2010
@@ -170,6 +170,15 @@
                 <include>org.ops4j.pax.url:pax-url-wrap</include>
             </includes>
         </dependencySet>
+       <dependencySet>
+            <outputDirectory>/system</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <outputFileNameMapping>org/apache/felix/karaf/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+            <includes>
+                <include>org.apache.felix.karaf:org.apache.felix.karaf.commons</include>
+            </includes>
+        </dependencySet>
         <dependencySet>
             <outputDirectory>/system</outputDirectory>
             <unpack>false</unpack>

Modified: felix/trunk/karaf/assembly/src/main/descriptors/windows-bin.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/descriptors/windows-bin.xml?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/descriptors/windows-bin.xml (original)
+++ felix/trunk/karaf/assembly/src/main/descriptors/windows-bin.xml Thu Mar  4 12:19:22 2010
@@ -168,6 +168,15 @@
             <useProjectArtifact>false</useProjectArtifact>
             <outputFileNameMapping>org/apache/felix/karaf/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
             <includes>
+                <include>org.apache.felix.karaf:org.apache.felix.karaf.commons</include>
+            </includes>
+        </dependencySet>
+        <dependencySet>
+            <outputDirectory>/system</outputDirectory>
+            <unpack>false</unpack>
+            <useProjectArtifact>false</useProjectArtifact>
+            <outputFileNameMapping>org/apache/felix/karaf/${artifact.artifactId}/${artifact.baseVersion}/${artifact.artifactId}-${artifact.baseVersion}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
+            <includes>
                 <include>org.apache.felix.karaf:org.apache.felix.karaf.management</include>
             </includes>
         </dependencySet>

Modified: felix/trunk/karaf/assembly/src/main/filtered-resources/etc/startup.properties
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/assembly/src/main/filtered-resources/etc/startup.properties?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/assembly/src/main/filtered-resources/etc/startup.properties (original)
+++ felix/trunk/karaf/assembly/src/main/filtered-resources/etc/startup.properties Thu Mar  4 12:19:22 2010
@@ -36,6 +36,7 @@
 #
 org/apache/aries/blueprint/org.apache.aries.blueprint/${aries.blueprint.version}/org.apache.aries.blueprint-${aries.blueprint.version}.jar=20
 
+org/apache/felix/karaf/org.apache.felix.karaf.commons/${pom.version}/org.apache.felix.karaf.commons-${pom.version}.jar=30
 org/apache/felix/gogo/org.apache.felix.gogo.runtime/${felix.gogo.version}/org.apache.felix.gogo.runtime-${felix.gogo.version}.jar=30
 org/apache/felix/karaf/shell/org.apache.felix.karaf.shell.console/${pom.version}/org.apache.felix.karaf.shell.console-${pom.version}.jar=30
 org/apache/felix/karaf/deployer/org.apache.felix.karaf.deployer.spring/${pom.version}/org.apache.felix.karaf.deployer.spring-${pom.version}.jar=30

Propchange: felix/trunk/karaf/commons/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Mar  4 12:19:22 2010
@@ -0,0 +1,5 @@
+target
+.classpath
+.project
+.settings
+*.i??

Added: felix/trunk/karaf/commons/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/commons/pom.xml?rev=918963&view=auto
==============================================================================
--- felix/trunk/karaf/commons/pom.xml (added)
+++ felix/trunk/karaf/commons/pom.xml Thu Mar  4 12:19:22 2010
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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/xsd/maven-4.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>
+    <artifactId>karaf</artifactId>
+    <groupId>org.apache.felix.karaf</groupId>
+    <version>1.5.0-SNAPSHOT</version>
+  </parent>
+
+  <groupId>org.apache.felix.karaf</groupId>
+  <artifactId>org.apache.felix.karaf.commons</artifactId>
+  <version>1.5.0-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+  <name>Apache Felix Karaf :: Commons</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>    
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <configuration>
+          <instructions>
+            <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
+            <Export-Package>${pom.artifactId}*;version=${project.version}</Export-Package>
+            <Import-Package>
+                !${pom.artifactId}*,
+                *
+            </Import-Package>
+            <_versionpolicy>${bnd.version.policy}</_versionpolicy>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
\ No newline at end of file

Copied: felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/VersionRange.java (from r918911, felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/VersionRange.java)
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/VersionRange.java?p2=felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/VersionRange.java&p1=felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/VersionRange.java&r1=918911&r2=918963&rev=918963&view=diff
==============================================================================
--- felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/VersionRange.java (original)
+++ felix/trunk/karaf/commons/src/main/java/org/apache/felix/karaf/commons/osgi/VersionRange.java Thu Mar  4 12:19:22 2010
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.felix.karaf.features.internal;
+package org.apache.felix.karaf.commons.osgi;
 
 import org.osgi.framework.Version;
 

Propchange: felix/trunk/karaf/deployer/war/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Mar  4 12:19:22 2010
@@ -0,0 +1,5 @@
+target
+.classpath
+.project
+.settings
+*.i??

Modified: felix/trunk/karaf/features/core/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/core/pom.xml?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/features/core/pom.xml (original)
+++ felix/trunk/karaf/features/core/pom.xml Thu Mar  4 12:19:22 2010
@@ -55,6 +55,11 @@
         </dependency>
 
         <dependency>
+            <groupId>org.apache.felix.karaf</groupId>
+            <artifactId>org.apache.felix.karaf.commons</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>org.apache.felix.karaf.shell</groupId>
             <artifactId>org.apache.felix.karaf.shell.console</artifactId>
         </dependency>

Modified: felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/FeaturesServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/FeaturesServiceImpl.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/FeaturesServiceImpl.java (original)
+++ felix/trunk/karaf/features/core/src/main/java/org/apache/felix/karaf/features/internal/FeaturesServiceImpl.java Thu Mar  4 12:19:22 2010
@@ -40,6 +40,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.apache.felix.karaf.commons.osgi.VersionRange;
 import org.apache.felix.karaf.features.FeaturesService;
 import org.apache.felix.karaf.features.Feature;
 import org.apache.felix.karaf.features.Repository;

Modified: felix/trunk/karaf/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/pom.xml?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/pom.xml (original)
+++ felix/trunk/karaf/pom.xml Thu Mar  4 12:19:22 2010
@@ -35,6 +35,7 @@
 
     <modules>
         <module>main</module>
+        <module>commons</module>
         <module>features</module>
         <module>admin</module>
         <module>deployer</module>
@@ -171,6 +172,11 @@
                 <version>${pom.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.felix.karaf</groupId>
+                <artifactId>org.apache.felix.karaf.commons</artifactId>
+                <version>${pom.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.apache.felix.karaf.deployer</groupId>
                 <artifactId>org.apache.felix.karaf.deployer.spring</artifactId>
                 <version>${pom.version}</version>

Modified: felix/trunk/karaf/shell/dev/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/pom.xml?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/pom.xml (original)
+++ felix/trunk/karaf/shell/dev/pom.xml Thu Mar  4 12:19:22 2010
@@ -37,6 +37,11 @@
     </dependency>
 
     <dependency>
+        <groupId>org.apache.felix.karaf</groupId>
+        <artifactId>org.apache.felix.karaf.commons</artifactId>
+    </dependency>
+
+    <dependency>
         <groupId>org.ops4j.pax.url</groupId>
         <artifactId>pax-url-wrap</artifactId>
     </dependency>

Modified: felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/ShowBundleTree.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/ShowBundleTree.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/ShowBundleTree.java (original)
+++ felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/ShowBundleTree.java Thu Mar  4 12:19:22 2010
@@ -48,16 +48,19 @@
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ShowBundleTree.class);
 
-    // a cache of all exported packages
-    private ExportedPackage[] allExportedPackages;
+    private Tree<Bundle> tree;
 
     @Override
     protected void doExecute(Bundle bundle) throws Exception {
+        long start = System.currentTimeMillis();
         // let's do the real work here
         printHeader(bundle);
-        Tree<Bundle> tree = createTree(bundle);
+        tree = new Tree<Bundle>(bundle);
+        createTree(bundle);
         printTree(tree);
         printDuplicatePackages(tree);
+        LOGGER.debug(format("Dependency tree calculated in %d ms",
+                            System.currentTimeMillis() - start));
     }
 
     /*
@@ -119,44 +122,69 @@
     /*
      * Creates the bundle tree
      */
-    protected Tree<Bundle> createTree(Bundle bundle) {
-        Tree<Bundle> tree = new Tree<Bundle>(bundle);
-        Set<Bundle> trail = new HashSet<Bundle>();
+    protected void createTree(Bundle bundle) {
         if (bundle.getState() >= Bundle.RESOLVED) {
-            createNode(tree, trail);
+            createNode(tree);
         } else {
-            for (Import i : Import.parse(String.valueOf(bundle.getHeaders().get("Import-Package")))) {
-                for (ExportedPackage ep : getPackageAdmin().getExportedPackages(i.getPackage())) {
-                    if (ep.getVersion().compareTo(i.getVersion()) >= 0) {
-                        if (!bundle.equals(ep.getExportingBundle())) {
-                            Node child = tree.addChild(ep.getExportingBundle());
-                            System.out.printf("- using %s to resolve import %s%n", ep.getExportingBundle(), i);
-                            createNode(child, trail);
-                        }
+            createNodesForImports(tree, bundle);
+        }
+    }
+
+    /*
+     * Creates nodes for the imports of the bundle (instead of reporting wiring information
+     */
+    private void createNodesForImports(Node node, Bundle bundle) {
+        for (Import i : Import.parse(String.valueOf(bundle.getHeaders().get("Import-Package")),
+                                     String.valueOf(bundle.getHeaders().get("Export-Package")))) {
+            createNodeForImport(node, bundle, i);
+        }
+    }
+
+    /*
+     * Create a child node for a given import (by finding a matching export in the currently installed bundles)
+     */
+    private void createNodeForImport(Node node, Bundle bundle, Import i) {
+        ExportedPackage[] exporters = getPackageAdmin().getExportedPackages(i.getPackage());
+        boolean foundMatch = false;
+        if (exporters != null) {
+            for (ExportedPackage ep : exporters) {
+                if (i.getVersion().isInRange(ep.getVersion())) {
+                    if (bundle.equals(ep.getExportingBundle())) {
+                        foundMatch = true;
+                    } else {
+                        Node child = node.addChild(ep.getExportingBundle());
+                        System.out.printf("- import %s: resolved using %s%n", i, ep.getExportingBundle());
+                        foundMatch = true;
+                        createNode(child);
                     }
                 }
             }
         }
-        return tree;
+        if (!foundMatch) {
+            System.out.printf("- import %s: WARNING - unable to find matching export%n", i);            
+        }
     }
 
     /*
      * Creates a node in the bundle tree
      */
-    private void createNode(Node<Bundle> node, Set<Bundle> trail) {
+    private void createNode(Node<Bundle> node) {
         Bundle bundle = node.getValue();
         Collection<Bundle> exporters = new HashSet<Bundle>();
         exporters.addAll(getWiredBundles(bundle).values());
 
         for (Bundle exporter : exporters) {
-            if (trail.contains(exporter)) {
-                LOGGER.debug(format("Skipping %s because it already exists in the current tree branch", exporter));
+            if (node.hasAncestor(exporter)) {                
+                LOGGER.debug(format("Skipping %s (already exists in the current branch)", exporter));
             } else {
-                trail.add(exporter);
-                Node child = node.addChild(exporter);
+                boolean existing = tree.flatten().contains(exporter);
                 LOGGER.debug(format("Adding %s as a dependency for %s", exporter, bundle));
-                createNode(child, trail);
-                trail.remove(exporter);
+                Node child = node.addChild(exporter);
+                if (existing) {
+                    LOGGER.debug(format("Skipping children of %s (already exists in another branch)", exporter));
+                } else {
+                    createNode(child);
+                }
             }
         }
     }

Modified: felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Import.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Import.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Import.java (original)
+++ felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Import.java Thu Mar  4 12:19:22 2010
@@ -19,7 +19,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.osgi.framework.Version;
+import org.apache.felix.karaf.commons.osgi.VersionRange;
 
 /**
  * Simple class to model an OSGi Import-Package
@@ -27,7 +27,7 @@
 public class Import {
 
     private final String packageName;
-    private final Version version;
+    private final VersionRange version;
     private final String value;
 
     /**
@@ -38,28 +38,24 @@
     protected Import(String value) {
         super();
         this.value = value;
-        if (value.contains(";")) {
-            this.packageName = value.split(";")[0];
-        } else {
-            this.packageName = value;
-        }
+        this.packageName = extractPackageName(value);
         if (value.contains("version=")) {
             this.version = extractVersion(value);
         } else {
-            this.version = Version.emptyVersion;
+            this.version = VersionRange.infiniteRange;
         }
     }
 
     /*
      * Extract the version from the string
      */
-    private Version extractVersion(String value) {
+    private VersionRange extractVersion(String value) {
         int begin = value.indexOf("version=") + 8;
         int end = value.indexOf(";", begin);
         if (end < 0) {
-            return Version.parseVersion(unquote(value.substring(begin)));
+            return VersionRange.parse(unquote(value.substring(begin)));
         } else {
-            return Version.parseVersion(unquote(value.substring(begin, end)));
+            return VersionRange.parse(unquote(value.substring(begin, end)));
         }
     }
 
@@ -74,7 +70,7 @@
         return packageName;  
     }
 
-    public Version getVersion() {
+    public VersionRange getVersion() {
         return version;
     }
 
@@ -89,9 +85,67 @@
      */
     public static List<Import> parse(String value) {
         LinkedList<Import> imports = new LinkedList<Import>();
-        for (String imp : value.split(",")) {
+        for (String imp : split(value)) {
             imports.add(new Import(imp));
         }
         return imports;
     }
+
+    /**
+     * Parse the value of an Import-Package META-INF header and return
+     * a list of Import instances, filtering out packages that are in the
+     * Export-Package META-INF header
+     *
+     * @param importValue the value of the Import-Package header
+     * @param exportValue the value of the Export-Package header
+     */
+    public static List<Import> parse(String importValue, String exportValue) {
+        LinkedList<String> exports = new LinkedList<String>();
+        for (String exp : split(exportValue)) {
+            exports.add(extractPackageName(exp));
+        }
+        LinkedList<Import> imports = new LinkedList<Import>();
+        for (Import imp : parse(importValue)) {
+            if (!exports.contains(imp.getPackage())) {
+                imports.add(imp);
+            }
+        }
+        return imports;
+    }
+
+    /*
+     * Extract the package name from the value
+     * e.g. org.apache.felix.karaf;version="1.x" -> org.apache.felix.karaf
+     */
+    private static String extractPackageName(String value) {
+        if (value.contains(";")) {
+            return value.split(";")[0];
+        } else {
+            return value;
+        }
+    }
+
+    /*
+     * Counts the number of quotes in a String value
+     */
+    private static int quotes(String value) {
+        return value.replaceAll("[^\"]", "").length();
+    }
+
+    /*
+     * Split the OSGi headers on the , symbol
+     */
+    private static List<String> split(String value) {
+        List<String> result = new LinkedList<String>();
+        String[] elements = value.split(",");
+        for (int i = 0; i < elements.length ; i++) {
+            if (quotes(elements[i]) % 2 == 1) {
+                // we probably split a version range, so joining it again with the next element
+                result.add(elements[i] + "," + elements[++i]);
+            } else {
+                result.add(elements[i]);
+            }
+        }
+        return result;
+    }
 }

Modified: felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Node.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Node.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Node.java (original)
+++ felix/trunk/karaf/shell/dev/src/main/java/org/apache/felix/karaf/shell/dev/util/Node.java Thu Mar  4 12:19:22 2010
@@ -93,6 +93,20 @@
         return result;
     }
 
+    /**
+     * Check if the node has an ancestor that represents the given value
+     *
+     * @param value the node value
+     * @return <code>true</code> it there's an ancestor that represents the value
+     */
+    public boolean hasAncestor(T value) {
+        if (parent == null) {
+            return false;
+        } else {
+            return value.equals(parent.value) || parent.hasAncestor(value);
+        }
+    }
+
     /*
      * Write this node to the PrintWriter.  It should be indented one step
      * further for every element in the indents array.  If an element in the

Modified: felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/ImportTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/ImportTest.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/ImportTest.java (original)
+++ felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/ImportTest.java Thu Mar  4 12:19:22 2010
@@ -20,8 +20,9 @@
 
 import static junit.framework.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+
+import org.apache.felix.karaf.commons.osgi.VersionRange;
 import org.junit.Test;
-import org.osgi.framework.Version;
 
 /**
  * Test cases for {@link org.apache.felix.karaf.shell.dev.util.Import}
@@ -38,7 +39,7 @@
     public void createWithPackageNameAndVersion() {
         Import i = new Import("org.wip.bar;version=\"2.0.0\"");
         assertEquals("org.wip.bar", i.getPackage());
-        assertEquals(new Version("2.0.0"), i.getVersion());
+        assertEquals(VersionRange.parse("2.0.0"), i.getVersion());
     }
 
     @Test
@@ -49,4 +50,22 @@
         assertEquals("org.wip.bar", imports.get(0).getPackage());
         assertEquals("org.wip.foo", imports.get(1).getPackage());
     }
+
+    @Test
+    public void createListOfImportsWithVersionRanges() {
+        List<Import> imports =
+                Import.parse("javax.activation;version=\"[0.0,2)\",javax.annotation;version=\"[0.0,2)\"");
+        assertNotNull(imports);
+        assertEquals(2, imports.size());
+        assertEquals("javax.activation", imports.get(0).getPackage());
+        assertEquals("javax.annotation", imports.get(1).getPackage());
+    }
+
+    @Test
+    public void createListOfImportsWithExports() {
+        List<Import> imports = Import.parse("org.wip.bar;version=\"2.0.0\",org.wip.foo", "org.wip.bar;version=\"2.0.0\"");
+        assertNotNull(imports);
+        assertEquals(1, imports.size());
+        assertEquals("org.wip.foo", imports.get(0).getPackage());
+    }
 }

Modified: felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/TreeTest.java
URL: http://svn.apache.org/viewvc/felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/TreeTest.java?rev=918963&r1=918962&r2=918963&view=diff
==============================================================================
--- felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/TreeTest.java (original)
+++ felix/trunk/karaf/shell/dev/src/test/java/org/apache/felix/karaf/shell/dev/util/TreeTest.java Thu Mar  4 12:19:22 2010
@@ -24,6 +24,7 @@
 import java.util.Set;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import org.junit.Test;
@@ -108,6 +109,19 @@
         assertTrue(elements.contains("grandchild"));
     }
 
+    @Test
+    public void hasAncestor() throws IOException {
+        Tree<String> tree = new Tree<String>("root");
+        Node<String> child1 = tree.addChild("child1");
+        child1.addChild("grandchild");
+        Node child2 = tree.addChild("child2");
+        Node node = child2.addChild("grandchild2");
+
+        assertTrue(node.hasAncestor("child2"));
+        assertTrue(node.hasAncestor("root"));
+        assertFalse(node.hasAncestor("child1"));
+    }
+
     private BufferedReader read(Tree<String> tree) {
         StringWriter writer = new StringWriter();
         tree.write(new PrintWriter(writer));

Propchange: felix/trunk/karaf/tooling/testing/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Thu Mar  4 12:19:22 2010
@@ -0,0 +1,5 @@
+target
+.classpath
+.project
+.settings
+*.i??