Improves the entry-related method implementations for the Bundle class
by generalizing entry access at the module layer, which makes it easy and
more consistent to provide access at the bundle layer.


git-svn-id: https://svn.apache.org/repos/asf/incubator/felix/trunk@424225 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
index 20b6566..42ed90c 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/Felix.java
@@ -21,6 +21,7 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.util.*;
+import java.util.zip.ZipEntry;
 
 import org.apache.felix.framework.cache.*;
 import org.apache.felix.framework.searchpolicy.*;
@@ -1059,13 +1060,13 @@
                 return null;
             }
         }
-        // Strip leading '/' if present.
-        if ((path.length() > 0) && (path.charAt(0) == '/'))
-        {
-            path = path.substring(1);
-        }
-        return bundle.getInfo().getCurrentModule()
-            .getContentLoader().getContent().getEntryPaths(path);
+
+        // Get the entry enumeration from the module content and
+        // create a wrapper enumeration to filter it.
+        Enumeration enumeration = new GetEntryPathsEnumeration(bundle, path);
+
+        // Return the enumeration if it has elements.
+        return (!enumeration.hasMoreElements()) ? null : enumeration;
     }
 
     /**
@@ -1074,30 +1075,17 @@
     public Enumeration findBundleEntries(
         BundleImpl bundle, String path, String filePattern, boolean recurse)
     {
-        // Strip leading '/' if present.
-        if ((path.length() > 0) && (path.charAt(0) == '/'))
-        {
-            path = path.substring(1);
-        }
-
-        // Sanity check the parameters.
-        if (path == null)
-        {
-            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
-        }
-        filePattern = (filePattern == null) ? "*" : filePattern;
-
 
         // Try to resolve the bundle per the spec.
         resolveBundles(new Bundle[] { bundle });
 
-        // Get the entry enumeration from the module content.
-        Enumeration enumeration = bundle.getInfo().getCurrentModule()
-            .getContentLoader().getContent().findEntries(path, filePattern, recurse);
+        // Get the entry enumeration from the module content and
+        // create a wrapper enumeration to filter it.
+        Enumeration enumeration =
+            new FindEntriesEnumeration(bundle, path, filePattern, recurse);
 
-        // Return a wrapper that will convert the entry strings to URLs.
-        return (enumeration == null)
-            ? null : new FindEntriesEnumeration(bundle, enumeration);
+        // Return the enumeration if it has elements.
+        return (!enumeration.hasMoreElements()) ? null : enumeration;
     }
 
     protected ServiceReference[] getBundleRegisteredServices(BundleImpl bundle)
@@ -3778,41 +3766,6 @@
     }
 
     //
-    // Miscellaneous inner classes.
-    //
-
-    /**
-     * Used by findBundleEntries() method to wrap the enumeration
-     * returned by IContent.findEntries() to convert the returned
-     * Strings to URLs.
-     */
-    private static class FindEntriesEnumeration implements Enumeration
-    {
-        private BundleImpl m_bundle = null;
-        private Enumeration m_enumeration = null;
-
-        public FindEntriesEnumeration(BundleImpl bundle, Enumeration enumeration)
-        {
-            m_bundle = bundle;
-            m_enumeration = enumeration;
-        }
-        
-        public boolean hasMoreElements()
-        {
-            return m_enumeration.hasMoreElements();
-        }
-
-        public Object nextElement()
-        {
-            URL url = 
-                ((ContentLoaderImpl) m_bundle.getInfo().getCurrentModule()
-                    .getContentLoader()).getResourceFromContent(
-                        (String) m_enumeration.nextElement());
-            return url;
-        }
-    }
-
-    //
     // Locking related methods.
     //
 
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
new file mode 100644
index 0000000..5eebfe1
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/FindEntriesEnumeration.java
@@ -0,0 +1,268 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.framework;
+
+import java.util.*;
+
+import org.apache.felix.framework.searchpolicy.ContentLoaderImpl;
+
+class FindEntriesEnumeration implements Enumeration
+{
+    private BundleImpl m_bundle = null;
+    private Enumeration m_enumeration = null;
+    private String m_path = null;
+    private String[] m_filePattern = null;
+    private boolean m_recurse = false;
+    private Object m_next = null;
+
+    public FindEntriesEnumeration(
+        BundleImpl bundle, String path, String filePattern, boolean recurse)
+    {
+        m_bundle = bundle;
+        m_path = path;
+        m_enumeration = m_bundle.getInfo().getCurrentModule()
+            .getContentLoader().getContent().getEntries();
+        m_recurse = recurse;
+
+        // Sanity check the parameters.
+        if (m_path == null)
+        {
+            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
+        }
+        // Strip leading '/' if present.
+        if ((m_path.length() > 0) && (m_path.charAt(0) == '/'))
+        {
+            m_path = m_path.substring(1);
+        }
+        // Add a '/' to the end if not present.
+        if ((m_path.length() > 0) && (m_path.charAt(path.length() - 1) != '/'))
+        {
+            m_path = m_path + "/";
+        }
+
+        // File pattern defaults to "*" if not specified.
+        filePattern = (filePattern == null) ? "*" : filePattern;
+
+        m_filePattern = parseSubstring(filePattern);
+
+        m_next = findNext();
+    }
+
+    public boolean hasMoreElements()
+    {
+        return (m_next != null);
+    }
+
+    public Object nextElement()
+    {
+        if (m_next == null)
+        {
+            throw new NoSuchElementException("No more entry paths.");
+        }
+        Object last = m_next;
+        m_next = findNext();
+        return last;
+    }
+
+    private Object findNext()
+    {
+        // This method filters the content entry enumeration, such that
+        // it only displays the contents of the directory specified by
+        // the path argument either recursively or not; much like using
+        // "ls -R" or "ls" to list the contents of a directory, respectively.
+        while (m_enumeration.hasMoreElements())
+        {
+            // Get the next entry name.
+            String entryName = (String) m_enumeration.nextElement();
+            // Check to see if it is a descendent of the specified path.
+            if (!entryName.equals(m_path) && entryName.startsWith(m_path))
+            {
+                // NOTE: We assume here that directories are not returned,
+                // unlike getEntryPaths() above, where directories are returned;
+                // this may or may not be the correct spec interpretation.
+
+                // If this is recursive, then simply verify that the
+                // entry is not a directory my making sure it does not
+                // end with '/'. If this is not recursive, then verify
+                // that the entry is a child of the path and not a
+                // grandchild by examining its remaining path length.
+                // This code uses the knowledge that content entries
+                // corresponding to directories end in '/'.
+                int idx = entryName.indexOf('/', m_path.length());
+                if ((m_recurse && (entryName.charAt(entryName.length() - 1) != '/'))
+                    || (idx < 0))
+                {
+                    // Get the last element of the path.
+                    idx = entryName.lastIndexOf('/');
+                    String lastElement = entryName;
+                    if (idx >= 0)
+                    {
+                        lastElement = entryName.substring(idx + 1);
+                    }
+                    // See if the file pattern matches the last element of the path.
+                    if (checkSubstring(m_filePattern, lastElement))
+                    {
+                        // Convert entry name into an entry URL.
+                        return ((ContentLoaderImpl) m_bundle.getInfo()
+                            .getCurrentModule().getContentLoader())
+                                .getResourceFromContent(entryName);
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    //
+    // The following substring-related code was lifted and modified
+    // from the LDAP parser code.
+    //
+
+    private static String[] parseSubstring(String target)
+    {
+        List pieces = new ArrayList();
+        StringBuffer ss = new StringBuffer();
+        // int kind = SIMPLE; // assume until proven otherwise
+        boolean wasStar = false; // indicates last piece was a star
+        boolean leftstar = false; // track if the initial piece is a star
+        boolean rightstar = false; // track if the final piece is a star
+
+        int idx = 0;
+
+        // We assume (sub)strings can contain leading and trailing blanks
+loop:   for (;;)
+        {
+            if (idx >= target.length())
+            {
+                if (wasStar)
+                {
+                    // insert last piece as "" to handle trailing star
+                    rightstar = true;
+                }
+                else
+                {
+                    pieces.add(ss.toString());
+                    // accumulate the last piece
+                    // note that in the case of
+                    // (cn=); this might be
+                    // the string "" (!=null)
+                }
+                ss.setLength(0);
+                break loop;
+            }
+    
+            char c = target.charAt(idx++);
+            if (c == '*')
+            {
+                if (wasStar)
+                {
+                    // encountered two successive stars;
+                    // I assume this is illegal
+                    throw new IllegalArgumentException("Invalid filter string: " + target);
+                }
+                if (ss.length() > 0)
+                {
+                    pieces.add(ss.toString()); // accumulate the pieces
+                    // between '*' occurrences
+                }
+                ss.setLength(0);
+                // if this is a leading star, then track it
+                if (pieces.size() == 0)
+                {
+                    leftstar = true;
+                }
+                ss.setLength(0);
+                wasStar = true;
+            }
+            else
+            {
+                wasStar = false;
+                ss.append(c);
+            }
+        }
+        if (leftstar || rightstar || pieces.size() > 1)
+        {
+            // insert leading and/or trailing "" to anchor ends
+            if (rightstar)
+            {
+                pieces.add("");
+            }
+            if (leftstar)
+            {
+                pieces.add(0, "");
+            }
+        }
+
+        return (String[]) pieces.toArray(new String[pieces.size()]);
+    }
+
+    private static boolean checkSubstring(String[] pieces, String s)
+    {
+        // Walk the pieces to match the string
+        // There are implicit stars between each piece,
+        // and the first and last pieces might be "" to anchor the match.
+        // assert (pieces.length > 1)
+        // minimal case is <string>*<string>
+
+        boolean result = false;
+        int len = pieces.length;
+
+loop:   for (int i = 0; i < len; i++)
+        {
+            String piece = (String) pieces[i];
+            int index = 0;
+            if (i == len - 1)
+            {
+                // this is the last piece
+                if (s.endsWith(piece))
+                {
+                    result = true;
+                }
+                else
+                {
+                    result = false;
+                }
+                break loop;
+            }
+            // initial non-star; assert index == 0
+            else if (i == 0)
+            {
+                if (!s.startsWith(piece))
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+            // assert i > 0 && i < len-1
+            else
+            {
+                // Sure wish stringbuffer supported e.g. indexOf
+                index = s.indexOf(piece, index);
+                if (index < 0)
+                {
+                    result = false;
+                    break loop;
+                }
+            }
+            // start beyond the matching piece
+            index += piece.length();
+        }
+
+        return result;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
new file mode 100644
index 0000000..13d5df3
--- /dev/null
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/framework/GetEntryPathsEnumeration.java
@@ -0,0 +1,100 @@
+/*
+ *   Copyright 2006 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.felix.framework;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+class GetEntryPathsEnumeration implements Enumeration
+{
+    private BundleImpl m_bundle = null;
+    private Enumeration m_enumeration = null;
+    private String m_path = null;
+    private Object m_next = null;
+
+    public GetEntryPathsEnumeration(BundleImpl bundle, String path)
+    {
+        m_bundle = bundle;
+        m_path = path;
+        m_enumeration = m_bundle.getInfo().getCurrentModule()
+            .getContentLoader().getContent().getEntries();
+
+        // Sanity check the parameters.
+        if (m_path == null)
+        {
+            throw new IllegalArgumentException("The path for findEntries() cannot be null.");
+        }
+        // Strip leading '/' if present.
+        if ((m_path.length() > 0) && (m_path.charAt(0) == '/'))
+        {
+            m_path = m_path.substring(1);
+        }
+        // Add a '/' to the end if not present.
+        if ((m_path.length() > 0) && (m_path.charAt(path.length() - 1) != '/'))
+        {
+            m_path = m_path + "/";
+        }
+
+        m_next = findNext();
+    }
+
+    public boolean hasMoreElements()
+    {
+        return (m_next != null);
+    }
+
+    public Object nextElement()
+    {
+        if (m_next == null)
+        {
+            throw new NoSuchElementException("No more entry paths.");
+        }
+        Object last = m_next;
+        m_next = findNext();
+        return last;
+    }
+
+    private Object findNext()
+    {
+        // This method filters the content entry enumeration, such that
+        // it only displays the contents of the directory specified by
+        // the path argument; much like using "ls" to list the contents
+        // of a directory.
+        while (m_enumeration.hasMoreElements())
+        {
+            // Get the next entry name.
+            String entryName = (String) m_enumeration.nextElement();
+            // Check to see if it is a descendent of the specified path.
+            if (!entryName.equals(m_path) && entryName.startsWith(m_path))
+            {
+                // Verify that it is a child of the path and not a
+                // grandchild by examining its remaining path length.
+                // This code uses the knowledge that content entries
+                // corresponding to directories end in '/'. It checks
+                // to see if the next occurrence of '/' is also the
+                // end of the string, which means that this entry
+                // represents a child directory of the path.
+                int idx = entryName.indexOf('/', m_path.length());
+                if ((idx < 0) || (idx == (entryName.length() - 1)))
+                {
+                    return entryName;
+                }
+            }
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ContentDirectoryContent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ContentDirectoryContent.java
index 267921d..44ac066 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ContentDirectoryContent.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/ContentDirectoryContent.java
@@ -112,31 +112,14 @@
         return m_content.getEntryAsStream(m_rootPath + name);
     }
 
-    public synchronized Enumeration getEntryPaths(String path)
+    public synchronized Enumeration getEntries()
     {
         if (!m_opened)
         {
             throw new IllegalStateException("ContentDirectoryContent is not open");
         }
 
-        if ((path.length() > 0) && (path.charAt(0) == '/'))
-        {
-            path = path.substring(1);
-        }
-
-        return new WrappedEnumeration(m_content.getEntryPaths(m_rootPath + path), m_rootPath);
-    }
-
-    public Enumeration findEntries(String path, String filePattern, boolean recurse)
-    {
-        // This IContent method supports Bundle.findEntries(), which is used to
-        // browse the bundle JAR file, not the bundle's class path. However,
-        // this implementation of IContent is used purely to add support for
-        // directories in the bundle class path, thus it will never represent
-        // the actual bundle content, so this method should never be called.
-        // For now we will leave this unimplemented and if it becomes necessary
-        // it can be implemented later.
-        throw new UnsupportedOperationException("Not implemented, since it should not be used.");
+        return new EntriesEnumeration(m_content.getEntries(), m_rootPath);
     }
 
     public String toString()
@@ -144,12 +127,12 @@
         return "CONTENT DIR " + m_rootPath + " (" + m_content + ")";
     }
 
-    private static class WrappedEnumeration implements Enumeration
+    private static class EntriesEnumeration implements Enumeration
     {
         private Enumeration m_enumeration = null;
         private String m_rootPath = null;
 
-        public WrappedEnumeration(Enumeration enumeration, String rootPath)
+        public EntriesEnumeration(Enumeration enumeration, String rootPath)
         {
             m_enumeration = enumeration;
             m_rootPath = rootPath;
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DirectoryContent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DirectoryContent.java
index 9868067..dbaa6e4 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DirectoryContent.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/DirectoryContent.java
@@ -18,8 +18,6 @@
 
 import java.io.*;
 import java.util.*;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
 
 public class DirectoryContent implements IContent
 {
@@ -130,22 +128,7 @@
         return new FileInputStream(new File(m_dir, name));
     }
 
-    public synchronized Enumeration getEntryPaths(String path)
-    {
-        if (!m_opened)
-        {
-            throw new IllegalStateException("DirectoryContent is not open");
-        }
-
-        if ((path.length() > 0) && (path.charAt(0) == '/'))
-        {
-            path = path.substring(1);
-        }
-
-        return new GetEntryPathsEnumeration(m_dir, path);
-    }
-
-    public Enumeration findEntries(String path, String filePattern, boolean recurse)
+    public synchronized Enumeration getEntries()
     {
         if (!m_opened)
         {
@@ -153,27 +136,27 @@
         }
 
         // Wrap entries enumeration to filter non-matching entries.
-        Enumeration e = new FindEntriesEnumeration(
-            m_dir, path, filePattern, recurse);
+        Enumeration e = new EntriesEnumeration(m_dir);
+
         // Spec says to return null if there are no entries.
         return (e.hasMoreElements()) ? e : null;
     }
 
-    private static class GetEntryPathsEnumeration implements Enumeration
+    public String toString()
     {
-        private File m_refDir = null;
-        private File m_listDir = null;
+        return "DIRECTORY " + m_dir;
+    }
+
+    private static class EntriesEnumeration implements Enumeration
+    {
+        private File m_dir = null;
         private File[] m_children = null;
         private int m_counter = 0;
 
-        public GetEntryPathsEnumeration(File refDir, String path)
+        public EntriesEnumeration(File dir)
         {
-            m_refDir = refDir;
-            m_listDir = new File(refDir, path);
-            if (m_listDir.isDirectory())
-            {
-                m_children = m_listDir.listFiles();
-            }
+            m_dir = dir;
+            m_children = listFilesRecursive(m_dir);
         }
 
         public boolean hasMoreElements()
@@ -187,10 +170,12 @@
             {
                 throw new NoSuchElementException("No more entry paths.");
             }
+
             // Remove the leading path of the reference directory, since the
             // entry paths are supposed to be relative to the root.
+// TODO: ML - Under Windows we will have to deal with drive letters, I think.
             StringBuffer sb = new StringBuffer(m_children[m_counter].getAbsolutePath());
-            sb.delete(0, m_refDir.getAbsolutePath().length() + 1);
+            sb.delete(0, m_dir.getAbsolutePath().length() + 1);
             // Add a '/' to the end of directory entries.
             if (m_children[m_counter].isDirectory())
             {
@@ -199,87 +184,6 @@
             m_counter++;
             return sb.toString();
         }
-    }
-
-    private static class FindEntriesEnumeration implements Enumeration
-    {
-        private File m_refDir = null;
-        private File m_listDir = null;
-        private String[] m_filePattern = null;
-        private boolean m_recurse = false;
-        private File[] m_children = null;
-        private int m_counter = 0;
-        private Object m_next = null;
-
-        public FindEntriesEnumeration(File refDir, String path, String filePattern, boolean recurse)
-        {
-            m_refDir = refDir;
-            m_listDir = new File(refDir, path);
-            m_filePattern = parseSubstring(filePattern);
-            m_recurse = recurse;
-            if (m_listDir.isDirectory())
-            {
-                if (m_recurse)
-                {
-                    m_children = listFilesRecursive(m_listDir);
-                }
-                else
-                {
-                    m_children = m_listDir.listFiles();
-                }
-            }
-            m_next = findNext();
-        }
-
-        public boolean hasMoreElements()
-        {
-            return (m_next != null);
-        }
-
-        public Object nextElement()
-        {
-            if (m_next == null)
-            {
-                throw new NoSuchElementException("No more entry paths.");
-            }
-            Object last = m_next;
-            m_next = findNext();
-            return last;
-        }
-
-        private Object findNext()
-        {
-            if ((m_children == null) || (m_counter >= m_children.length))
-            {
-                return null;
-            }
-
-            // NOTE: We assume here that directories are not returned,
-            // unlike getEntryPaths() above, where directories are returned;
-            // this may or may not be the correct spec interpretation.
-
-            // Ignore directories and file that do not match the file pattern.
-            while ((m_counter < m_children.length) &&
-                (m_children[m_counter].isDirectory() ||
-                !checkSubstring(m_filePattern, m_children[m_counter].getName())))
-            {
-                m_counter++;
-            }
-
-            // Return null if there is no more matches.
-            if (m_counter >= m_children.length)
-            {
-                return null;
-            }
-
-            // Remove the leading path of the reference directory, since the
-            // entry paths are supposed to be relative to the root.
-            StringBuffer sb = new StringBuffer(m_children[m_counter].getAbsolutePath());
-            sb.delete(0, m_refDir.getAbsolutePath().length() + 1);
-            m_counter++;
-
-            return sb.toString();
-        }
 
         public File[] listFilesRecursive(File dir)
         {
@@ -302,141 +206,4 @@
             return combined;
         }
     }
-
-    //
-    // The following substring-related code was lifted and modified
-    // from the LDAP parser code.
-    //
-
-    private static String[] parseSubstring(String target)
-    {
-        List pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
-        // int kind = SIMPLE; // assume until proven otherwise
-        boolean wasStar = false; // indicates last piece was a star
-        boolean leftstar = false; // track if the initial piece is a star
-        boolean rightstar = false; // track if the final piece is a star
-
-        int idx = 0;
-
-        // We assume (sub)strings can contain leading and trailing blanks
-loop:   for (;;)
-        {
-            if (idx >= target.length())
-            {
-                if (wasStar)
-                {
-                    // insert last piece as "" to handle trailing star
-                    rightstar = true;
-                }
-                else
-                {
-                    pieces.add(ss.toString());
-                    // accumulate the last piece
-                    // note that in the case of
-                    // (cn=); this might be
-                    // the string "" (!=null)
-                }
-                ss.setLength(0);
-                break loop;
-            }
-
-            char c = target.charAt(idx++);
-            if (c == '*')
-            {
-                if (wasStar)
-                {
-                    // encountered two successive stars;
-                    // I assume this is illegal
-                    throw new IllegalArgumentException("Invalid filter string: " + target);
-                }
-                if (ss.length() > 0)
-                {
-                    pieces.add(ss.toString()); // accumulate the pieces
-                    // between '*' occurrences
-                }
-                ss.setLength(0);
-                // if this is a leading star, then track it
-                if (pieces.size() == 0)
-                {
-                    leftstar = true;
-                }
-                ss.setLength(0);
-                wasStar = true;
-            }
-            else
-            {
-                wasStar = false;
-                ss.append(c);
-            }
-        }
-        if (leftstar || rightstar || pieces.size() > 1)
-        {
-            // insert leading and/or trailing "" to anchor ends
-            if (rightstar)
-            {
-                pieces.add("");
-            }
-            if (leftstar)
-            {
-                pieces.add(0, "");
-            }
-        }
-        return (String[]) pieces.toArray(new String[pieces.size()]);
-    }
-
-    private static boolean checkSubstring(String[] pieces, String s)
-    {
-        // Walk the pieces to match the string
-        // There are implicit stars between each piece,
-        // and the first and last pieces might be "" to anchor the match.
-        // assert (pieces.length > 1)
-        // minimal case is <string>*<string>
-
-        boolean result = false;
-        int len = pieces.length;
-
-loop:   for (int i = 0; i < len; i++)
-        {
-            String piece = (String) pieces[i];
-            int index = 0;
-            if (i == len - 1)
-            {
-                // this is the last piece
-                if (s.endsWith(piece))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
-            }
-            // initial non-star; assert index == 0
-            else if (i == 0)
-            {
-                if (!s.startsWith(piece))
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // assert i > 0 && i < len-1
-            else
-            {
-                // Sure wish stringbuffer supported e.g. indexOf
-                index = s.indexOf(piece, index);
-                if (index < 0)
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // start beyond the matching piece
-            index += piece.length();
-        }
-
-        return result;
-    }
 }
\ No newline at end of file
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
index c8a5392..60965ce 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/IContent.java
@@ -28,6 +28,16 @@
     public byte[] getEntry(String name);
     public InputStream getEntryAsStream(String name)
         throws IOException;
-    public Enumeration getEntryPaths(String path);
-    public Enumeration findEntries(String path, String filePattern, boolean recurse);
-}
\ No newline at end of file
+
+    /**
+     * <p>
+     * Returns an enumeration of entry names as <tt>String</tt> objects.
+     * An entry name is a path constructed with '/' as path element
+     * separators and is relative to the root of the content. Entry names
+     * for entries that represent directories should end with the '/'
+     * character.
+     * </p>
+     * @ returns An enumeration of entry names or <tt>null</tt>.
+    **/ 
+    public Enumeration getEntries();
+}
diff --git a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java
index 6f7dc0b..6a89fbc 100644
--- a/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java
+++ b/org.apache.felix.framework/src/main/java/org/apache/felix/moduleloader/JarContent.java
@@ -224,7 +224,7 @@
         return is;
     }
 
-    public synchronized Enumeration getEntryPaths(String path)
+    public synchronized Enumeration getEntries()
     {
         if (!m_opened)
         {
@@ -246,36 +246,8 @@
         }
 
         // Wrap entries enumeration to filter non-matching entries.
-        Enumeration e = new GetEntryPathsEnumeration(m_jarFile.entries(), path);
-        // Spec says to return null if there are no entries.
-        return (e.hasMoreElements()) ? e : null;
-    }
+        Enumeration e = new EntriesEnumeration(m_jarFile.entries());
 
-    public synchronized Enumeration findEntries(
-        String path, String filePattern, boolean recurse)
-    {
-        if (!m_opened)
-        {
-            throw new IllegalStateException("JarContent is not open");
-        }
-
-        // Open JAR file if not already opened.
-        if (m_jarFile == null)
-        {
-            try
-            {
-                openJarFile();
-            }
-            catch (IOException ex)
-            {
-                System.err.println("JarContent: " + ex);
-                return null;
-            }
-        }
-
-        // Wrap entries enumeration to filter non-matching entries.
-        Enumeration e = new FindEntriesEnumeration(
-            m_jarFile.entries(), path, filePattern, recurse);
         // Spec says to return null if there are no entries.
         return (e.hasMoreElements()) ? e : null;
     }
@@ -293,286 +265,24 @@
         return "JAR " + m_file.getPath();
     }
 
-    private static class GetEntryPathsEnumeration implements Enumeration
+    private static class EntriesEnumeration implements Enumeration
     {
         private Enumeration m_enumeration = null;
-        private String m_path = null;
         private Object m_next = null;
 
-        public GetEntryPathsEnumeration(Enumeration enumeration, String path)
+        public EntriesEnumeration(Enumeration enumeration)
         {
             m_enumeration = enumeration;
-            // Add a '/' to the end if not present.
-            m_path = (path.length() > 0) && (path.charAt(path.length() - 1) != '/')
-                ? path + "/" : path;
-            m_next = findNext();
         }
 
         public boolean hasMoreElements()
         {
-            return (m_next != null);
+            return m_enumeration.hasMoreElements();
         }
 
         public Object nextElement()
         {
-            if (m_next == null)
-            {
-                throw new NoSuchElementException("No more entry paths.");
-            }
-            Object last = m_next;
-            m_next = findNext();
-            return last;
+            return ((ZipEntry) m_enumeration.nextElement()).getName();
         }
-
-        private Object findNext()
-        {
-            // This method filters the entries of the zip file, such that
-            // it only displays the contents of the directory specified by
-            // the path argument; much like using "ls" to list the contents
-            // of a directory.
-            while (m_enumeration.hasMoreElements())
-            {
-                // Get the next zip entry.
-                ZipEntry entry = (ZipEntry) m_enumeration.nextElement();
-                // Check to see if it is a descendent of the specified path.
-                if (!entry.getName().equals(m_path) && entry.getName().startsWith(m_path))
-                {
-                    // Verify that it is a child of the path and not a
-                    // grandchild by examining its remaining path length.
-                    // This code uses the knowledge that zip entries
-                    // corresponding to directories end in '/'. It checks
-                    // to see if the next occurrence of '/' is also the
-                    // end of the string, which means that this entry
-                    // represents a child directory of the path.
-                    int idx = entry.getName().indexOf('/', m_path.length());
-                    if ((idx < 0) || (idx == (entry.getName().length() - 1)))
-                    {
-                        return entry.getName();
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    private static class FindEntriesEnumeration implements Enumeration
-    {
-        private Enumeration m_enumeration = null;
-        private String m_path = null;
-        private String[] m_filePattern = null;
-        private boolean m_recurse = false;
-        private Object m_next = null;
-
-        public FindEntriesEnumeration(
-            Enumeration enumeration, String path, String filePattern, boolean recurse)
-        {
-            m_enumeration = enumeration;
-            // Add a '/' to the end if not present.
-            m_path = (path.length() > 0) && (path.charAt(path.length() - 1) != '/')
-                ? path + "/" : path;
-            m_filePattern = parseSubstring(filePattern);
-            m_recurse = recurse;
-            m_next = findNext();
-        }
-
-        public boolean hasMoreElements()
-        {
-            return (m_next != null);
-        }
-
-        public Object nextElement()
-        {
-            if (m_next == null)
-            {
-                throw new NoSuchElementException("No more entry paths.");
-            }
-            Object last = m_next;
-            m_next = findNext();
-            return last;
-        }
-
-        private Object findNext()
-        {
-            // This method filters the entries of the zip file, such that
-            // it only displays the contents of the directory specified by
-            // the path argument either recursively or not; much like using
-            // "ls -R" or "ls" to list the contents of a directory, respectively.
-            while (m_enumeration.hasMoreElements())
-            {
-                // Get the next zip entry.
-                ZipEntry entry = (ZipEntry) m_enumeration.nextElement();
-                String entryName = entry.getName();
-                // Check to see if it is a descendent of the specified path.
-                if (!entryName.equals(m_path) && entryName.startsWith(m_path))
-                {
-                    // NOTE: We assume here that directories are not returned,
-                    // unlike getEntryPaths() above, where directories are returned;
-                    // this may or may not be the correct spec interpretation.
-
-                    // If this is recursive, then simply verify that the
-                    // entry is not a directory my making sure it does not
-                    // end with '/'. If this is not recursive, then verify
-                    // that the entry is a child of the path and not a
-                    // grandchild by examining its remaining path length.
-                    // This code uses the knowledge that zip entries
-                    // corresponding to directories end in '/'.
-                    int idx = entryName.indexOf('/', m_path.length());
-                    if ((m_recurse && (entryName.charAt(entryName.length() - 1) != '/'))
-                        || (idx < 0))
-                    {
-                        // Get the last element of the path.
-                        idx = entryName.lastIndexOf('/');
-                        String lastElement = entryName;
-                        if (idx >= 0)
-                        {
-                            lastElement = entryName.substring(idx + 1);
-                        }
-                        // See if the file pattern matches the last element of the path.
-                        if (checkSubstring(m_filePattern, lastElement))
-                        {
-                            return entry.getName();
-                        }
-                    }
-                }
-            }
-            return null;
-        }
-    }
-
-    //
-    // The following substring-related code was lifted and modified
-    // from the LDAP parser code.
-    //
-
-    private static String[] parseSubstring(String target)
-    {
-        List pieces = new ArrayList();
-        StringBuffer ss = new StringBuffer();
-        // int kind = SIMPLE; // assume until proven otherwise
-        boolean wasStar = false; // indicates last piece was a star
-        boolean leftstar = false; // track if the initial piece is a star
-        boolean rightstar = false; // track if the final piece is a star
-
-        int idx = 0;
-
-        // We assume (sub)strings can contain leading and trailing blanks
-loop:   for (;;)
-        {
-            if (idx >= target.length())
-            {
-                if (wasStar)
-                {
-                    // insert last piece as "" to handle trailing star
-                    rightstar = true;
-                }
-                else
-                {
-                    pieces.add(ss.toString());
-                    // accumulate the last piece
-                    // note that in the case of
-                    // (cn=); this might be
-                    // the string "" (!=null)
-                }
-                ss.setLength(0);
-                break loop;
-            }
-
-            char c = target.charAt(idx++);
-            if (c == '*')
-            {
-                if (wasStar)
-                {
-                    // encountered two successive stars;
-                    // I assume this is illegal
-                    throw new IllegalArgumentException("Invalid filter string: " + target);
-                }
-                if (ss.length() > 0)
-                {
-                    pieces.add(ss.toString()); // accumulate the pieces
-                    // between '*' occurrences
-                }
-                ss.setLength(0);
-                // if this is a leading star, then track it
-                if (pieces.size() == 0)
-                {
-                    leftstar = true;
-                }
-                ss.setLength(0);
-                wasStar = true;
-            }
-            else
-            {
-                wasStar = false;
-                ss.append(c);
-            }
-        }
-        if (leftstar || rightstar || pieces.size() > 1)
-        {
-            // insert leading and/or trailing "" to anchor ends
-            if (rightstar)
-            {
-                pieces.add("");
-            }
-            if (leftstar)
-            {
-                pieces.add(0, "");
-            }
-        }
-        return (String[]) pieces.toArray(new String[pieces.size()]);
-    }
-
-    private static boolean checkSubstring(String[] pieces, String s)
-    {
-        // Walk the pieces to match the string
-        // There are implicit stars between each piece,
-        // and the first and last pieces might be "" to anchor the match.
-        // assert (pieces.length > 1)
-        // minimal case is <string>*<string>
-
-        boolean result = false;
-        int len = pieces.length;
-
-loop:   for (int i = 0; i < len; i++)
-        {
-            String piece = (String) pieces[i];
-            int index = 0;
-            if (i == len - 1)
-            {
-                // this is the last piece
-                if (s.endsWith(piece))
-                {
-                    result = true;
-                }
-                else
-                {
-                    result = false;
-                }
-                break loop;
-            }
-            // initial non-star; assert index == 0
-            else if (i == 0)
-            {
-                if (!s.startsWith(piece))
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // assert i > 0 && i < len-1
-            else
-            {
-                // Sure wish stringbuffer supported e.g. indexOf
-                index = s.indexOf(piece, index);
-                if (index < 0)
-                {
-                    result = false;
-                    break loop;
-                }
-            }
-            // start beyond the matching piece
-            index += piece.length();
-        }
-
-        return result;
     }
 }
\ No newline at end of file