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