summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Ross2013-08-29 09:30:45 (EDT)
committer Thomas Watson2013-08-30 16:23:18 (EDT)
commit4af4881573f98cb0eab92922c6302908fd56b389 (patch)
tree0c1f40d44882f5e2312453f5120b120fca12e31c
parentf71c31ff5bfff75903926ab7448b1f14a8f91c2c (diff)
downloadrt.equinox.framework-4af4881573f98cb0eab92922c6302908fd56b389.zip
rt.equinox.framework-4af4881573f98cb0eab92922c6302908fd56b389.tar.gz
rt.equinox.framework-4af4881573f98cb0eab92922c6302908fd56b389.tar.bz2
Bug 416073 - Optimize Storage.listEntryPaths for wildcards and recursion.
The first optimization consisted of adding an additional method to BundleFile with the following signature: abstract public void getEntryPaths(String path, boolean recursive) This allows the bundle file to return all descendants under the specified path rather than only its children. In turn, this allowed for the removal of the loop in Storage.listEntryPaths that made multiple calls to the bundle file for the same data. The second optimization was to replace List with a Set in BundleLoader.listResources and Storage.listEntryPaths to achieve constant lookup time for contains(). A LinkedHashSet was used to maintain the original ordering. As part of this work, a bundle file decorator class (BundleFileWrapper) was introduced in order to shield clients from future changes to BundleFile. As a result of these changes, org.eclipse.equinox.transforms and org.eclipse.equinox.weaving in rt.equinox.bundles required updates. Fixed synthetic access compiler warning in BundleLoader. Removed all @since 3.2 annotations from package org.eclipse.osgi.storage.bundlefile. Refactored SignedBundleFile so that BundleFileWrapper did not need to accept a null bundle file in the constructor. Fixed a failure in DiscardBundleTests caused by not being able to setLastModified on a file locked by the framework.
-rw-r--r--bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginConverterHook.java46
-rw-r--r--bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java5
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java49
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java18
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java30
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java4
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java28
-rwxr-xr-xbundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapper.java86
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java44
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java42
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java1
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java7
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java3
-rw-r--r--bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java45
20 files changed, 232 insertions, 200 deletions
diff --git a/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginConverterHook.java b/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginConverterHook.java
index 392155e..b7fd917 100644
--- a/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginConverterHook.java
+++ b/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginConverterHook.java
@@ -12,14 +12,23 @@ package org.eclipse.osgi.compatibility.plugins;
import java.io.File;
import java.io.IOException;
-import java.util.Enumeration;
+
import org.eclipse.osgi.framework.util.Headers;
-import org.eclipse.osgi.internal.hookregistry.*;
+import org.eclipse.osgi.internal.hookregistry.ActivatorHookFactory;
+import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
+import org.eclipse.osgi.internal.hookregistry.HookConfigurator;
+import org.eclipse.osgi.internal.hookregistry.HookRegistry;
import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
import org.eclipse.osgi.service.pluginconversion.PluginConverter;
import org.eclipse.osgi.storage.BundleInfo.Generation;
-import org.eclipse.osgi.storage.bundlefile.*;
-import org.osgi.framework.*;
+import org.eclipse.osgi.storage.bundlefile.BundleEntry;
+import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
+import org.eclipse.osgi.storage.bundlefile.FileBundleEntry;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
public class PluginConverterHook implements HookConfigurator {
@Override
@@ -34,26 +43,11 @@ public class PluginConverterHook implements HookConfigurator {
hookRegistry.addBundleFileWrapperFactoryHook(new BundleFileWrapperFactoryHook() {
@Override
- public BundleFile wrapBundleFile(final BundleFile bundleFile, Generation generation, boolean base) {
+ public BundleFileWrapper wrapBundleFile(final BundleFile bundleFile, Generation generation, boolean base) {
if (!base) {
return null;
}
- return new BundleFile(bundleFile.getBaseFile()) {
-
- @Override
- public void open() throws IOException {
- bundleFile.open();
- }
-
- @Override
- public File getFile(String path, boolean nativeCode) {
- return bundleFile.getFile(path, nativeCode);
- }
-
- @Override
- public Enumeration<String> getEntryPaths(String path) {
- return bundleFile.getEntryPaths(path);
- }
+ return new BundleFileWrapper(bundleFile) {
@Override
public BundleEntry getEntry(String path) {
@@ -85,16 +79,6 @@ public class PluginConverterHook implements HookConfigurator {
throw new RuntimeException(e);
}
}
-
- @Override
- public boolean containsDir(String dir) {
- return bundleFile.containsDir(dir);
- }
-
- @Override
- public void close() throws IOException {
- bundleFile.close();
- }
};
}
});
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
index 77adecc..c519ad8 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/DiscardBundleTests.java
@@ -145,6 +145,10 @@ public class DiscardBundleTests extends AbstractBundleTests {
try {
equinox = restart(equinox, configuration);
assertNotDiscarded(location, equinox);
+ // Attempting to touch the file with equinox still running
+ // will sometimes result in failure presumably due to a locked
+ // file.
+ stop(equinox);
touchFile(bundleFile);
equinox = restart(equinox, configuration);
if (discard)
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java
index d2e4e55..cfcfc49 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/hookregistry/BundleFileWrapperFactoryHook.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 IBM Corporation and others.
+ * Copyright (c) 2012, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -13,6 +13,7 @@ package org.eclipse.osgi.internal.hookregistry;
import org.eclipse.osgi.storage.BundleInfo.Generation;
import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.BundleFileWrapper;
/**
* A factory that wraps bundle file objects.
@@ -27,6 +28,6 @@ public interface BundleFileWrapperFactoryHook {
* @return a wrapped bundle file for the specified content, or null if the bundle content
* is not wrapped.
*/
- BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base);
+ BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base);
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
index b1d50d3..ddda31f 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/loader/BundleLoader.java
@@ -213,10 +213,11 @@ public class BundleLoader implements ModuleLoader {
if (System.getSecurityManager() == null) {
classloader = createClassLoaderPrivledged(parent, generation.getBundleInfo().getStorage().getConfiguration(), this, generation, hooks);
} else {
+ final ClassLoader cl = parent;
classloader = AccessController.doPrivileged(new PrivilegedAction<ModuleClassLoader>() {
@Override
public ModuleClassLoader run() {
- return createClassLoaderPrivledged(parent, generation.getBundleInfo().getStorage().getConfiguration(), BundleLoader.this, generation, hooks);
+ return createClassLoaderPrivledged(cl, generation.getBundleInfo().getStorage().getConfiguration(), BundleLoader.this, generation, hooks);
}
});
}
@@ -678,7 +679,9 @@ public class BundleLoader implements ModuleLoader {
}
boolean localSearch = (options & BundleWiring.LISTRESOURCES_LOCAL) != 0;
- List<String> result = new ArrayList<String>();
+ // Use LinkedHashSet for optimized performance of contains() plus
+ // ordering guarantees.
+ LinkedHashSet<String> result = new LinkedHashSet<String>();
Set<String> importedPackages = new HashSet<String>(0);
for (String name : packages) {
// look for import source
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
index dc20915..f176377 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignatureBlockProcessor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2012 IBM Corporation and others. All rights reserved.
+ * Copyright (c) 2007, 2013 IBM Corporation and others. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
@@ -36,7 +36,7 @@ public class SignatureBlockProcessor implements SignedContentConstants {
}
public SignedContentImpl process() throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
- BundleFile wrappedBundleFile = signedBundle.getWrappedBundleFile();
+ BundleFile wrappedBundleFile = signedBundle.getBundleFile();
BundleEntry be = wrappedBundleFile.getEntry(META_INF_MANIFEST_MF);
if (be == null)
return createUnsignedContent();
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
index ab610f2..e912787 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2006, 2012 IBM Corporation and others.
+ * Copyright (c) 2006, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,15 +11,14 @@
package org.eclipse.osgi.internal.signedcontent;
-import java.io.*;
+import java.io.IOException;
+import java.io.InputStream;
import java.net.URL;
import java.security.*;
import java.security.cert.*;
import java.util.Date;
-import java.util.Enumeration;
import org.eclipse.osgi.signedcontent.*;
-import org.eclipse.osgi.storage.bundlefile.BundleEntry;
-import org.eclipse.osgi.storage.bundlefile.BundleFile;
+import org.eclipse.osgi.storage.bundlefile.*;
import org.eclipse.osgi.util.NLS;
/**
@@ -27,21 +26,19 @@ import org.eclipse.osgi.util.NLS;
* signatures. It requires full signing of the manifest by all signers. If no
* signatures are found, the classes and resources are retrieved without checks.
*/
-public class SignedBundleFile extends BundleFile implements SignedContentConstants, SignedContent {
- private BundleFile wrappedBundleFile;
+public class SignedBundleFile extends BundleFileWrapper implements SignedContentConstants, SignedContent {
SignedContentImpl signedContent;
private final int supportFlags;
private final SignedBundleHook signedBundleHook;
- SignedBundleFile(SignedContentImpl signedContent, int supportFlags, SignedBundleHook signedBundleHook) {
- super(null);
+ SignedBundleFile(BundleFile bundleFile, SignedContentImpl signedContent, int supportFlags, SignedBundleHook signedBundleHook) {
+ super(bundleFile);
this.signedContent = signedContent;
this.supportFlags = supportFlags;
this.signedBundleHook = signedBundleHook;
}
- void setBundleFile(BundleFile bundleFile) throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
- wrappedBundleFile = bundleFile;
+ void initializeSignedContent() throws IOException, InvalidKeyException, SignatureException, CertificateException, NoSuchAlgorithmException, NoSuchProviderException {
if (signedContent == null) {
SignatureBlockProcessor signatureProcessor = new SignatureBlockProcessor(this, supportFlags, signedBundleHook);
signedContent = signatureProcessor.process();
@@ -50,15 +47,11 @@ public class SignedBundleFile extends BundleFile implements SignedContentConstan
}
}
- public File getFile(String path, boolean nativeCode) {
- return wrappedBundleFile.getFile(path, nativeCode);
- }
-
public BundleEntry getEntry(String path) {
// strip off leading slashes so we can ensure the path matches the one provided in the manifest.
if (path.length() > 0 && path.charAt(0) == '/')
path = path.substring(1);
- BundleEntry be = wrappedBundleFile.getEntry(path);
+ BundleEntry be = getBundleFile().getEntry(path);
if ((supportFlags & SignedBundleHook.VERIFY_RUNTIME) == 0 || signedContent == null)
return be;
if (path.startsWith(META_INF)) {
@@ -82,26 +75,6 @@ public class SignedBundleFile extends BundleFile implements SignedContentConstan
return new SignedBundleEntry(be);
}
- public Enumeration<String> getEntryPaths(String path) {
- return wrappedBundleFile.getEntryPaths(path);
- }
-
- public void close() throws IOException {
- wrappedBundleFile.close();
- }
-
- public void open() throws IOException {
- wrappedBundleFile.open();
- }
-
- public boolean containsDir(String dir) {
- return wrappedBundleFile.containsDir(dir);
- }
-
- public File getBaseFile() {
- return wrappedBundleFile.getBaseFile();
- }
-
class SignedBundleEntry extends BundleEntry {
BundleEntry nestedEntry;
@@ -138,10 +111,6 @@ public class SignedBundleFile extends BundleFile implements SignedContentConstan
}
- BundleFile getWrappedBundleFile() {
- return wrappedBundleFile;
- }
-
SignedContentImpl getSignedContent() {
return signedContent;
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
index fe0fceb..45ea87b 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/signedcontent/SignedBundleHook.java
@@ -146,26 +146,26 @@ public class SignedBundleHook implements ActivatorHookFactory, BundleFileWrapper
}
}
- public BundleFile wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) {
+ public BundleFileWrapper wrapBundleFile(BundleFile bundleFile, Generation generation, boolean base) {
try {
if (bundleFile != null) {
StorageHookImpl hook = generation.getStorageHook(SignedStorageHook.class);
SignedBundleFile signedBaseFile;
if (base && hook != null) {
- signedBaseFile = new SignedBundleFile(hook.signedContent, supportSignedBundles, this);
+ signedBaseFile = new SignedBundleFile(bundleFile, hook.signedContent, supportSignedBundles, this);
if (hook.signedContent == null) {
- signedBaseFile.setBundleFile(bundleFile);
+ signedBaseFile.initializeSignedContent();
SignedContentImpl signedContent = signedBaseFile.getSignedContent();
hook.signedContent = signedContent != null && signedContent.isSigned() ? signedContent : null;
}
} else
- signedBaseFile = new SignedBundleFile(null, supportSignedBundles, this);
- signedBaseFile.setBundleFile(bundleFile);
+ signedBaseFile = new SignedBundleFile(bundleFile, null, supportSignedBundles, this);
+ signedBaseFile.initializeSignedContent();
SignedContentImpl signedContent = signedBaseFile.getSignedContent();
if (signedContent != null && signedContent.isSigned()) {
// only use the signed file if there are certs
signedContent.setContent(signedBaseFile);
- bundleFile = signedBaseFile;
+ return new BundleFileWrapper(signedBaseFile);
}
}
} catch (IOException e) {
@@ -173,7 +173,7 @@ public class SignedBundleHook implements ActivatorHookFactory, BundleFileWrapper
} catch (GeneralSecurityException e) {
log("Bad bundle file: " + bundleFile.getBaseFile(), FrameworkLogEntry.WARNING, e); //$NON-NLS-1$
}
- return bundleFile;
+ return null;
}
public void addHooks(HookRegistry hookRegistry) {
@@ -210,9 +210,9 @@ public class SignedBundleHook implements ActivatorHookFactory, BundleFileWrapper
temp.close();
contentBundleFile = new ZipBundleFile(content, null, null, container.getConfiguration().getDebug());
}
- SignedBundleFile result = new SignedBundleFile(null, VERIFY_ALL, this);
+ SignedBundleFile result = new SignedBundleFile(contentBundleFile, null, VERIFY_ALL, this);
try {
- result.setBundleFile(contentBundleFile);
+ result.initializeSignedContent();
} catch (InvalidKeyException e) {
throw (InvalidKeyException) new InvalidKeyException(NLS.bind(SignedContentMessages.Factory_SignedContent_Error, content)).initCause(e);
} catch (SignatureException e) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
index fe4d81c..318f78b 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/Storage.java
@@ -864,7 +864,7 @@ public class Storage {
List<BundleFileWrapperFactoryHook> wrapperFactories = getConfiguration().getHookRegistry().getBundleFileWrapperFactoryHooks();
BundleFileWrapperChain wrapped = wrapperFactories.isEmpty() ? null : new BundleFileWrapperChain(bundleFile, null);
for (BundleFileWrapperFactoryHook wrapperFactory : wrapperFactories) {
- BundleFile wrapperBundle = wrapperFactory.wrapBundleFile(bundleFile, generation, isBase);
+ BundleFileWrapper wrapperBundle = wrapperFactory.wrapBundleFile(bundleFile, generation, isBase);
if (wrapperBundle != null && wrapperBundle != bundleFile)
bundleFile = wrapped = new BundleFileWrapperChain(wrapperBundle, wrapped);
}
@@ -1473,12 +1473,13 @@ public class Storage {
* @see BundleWiring#listResources(String, String, int)
*/
public static List<String> listEntryPaths(List<BundleFile> bundleFiles, String path, String filePattern, int options) {
- // a list used to store the results of the search
- List<String> pathList = new ArrayList<String>();
+ // Use LinkedHashSet for optimized performance of contains() plus
+ // ordering guarantees.
+ LinkedHashSet<String> pathList = new LinkedHashSet<String>();
Filter patternFilter = null;
Hashtable<String, String> patternProps = null;
if (filePattern != null) {
- // Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file.
+ // Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file.
// Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested.
if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) {
if (path.length() == 0)
@@ -1489,7 +1490,7 @@ public class Storage {
if (bundleFile.getEntry(path) != null && !pathList.contains(path))
pathList.add(path);
}
- return pathList;
+ return new ArrayList<String>(pathList);
}
// For when the file pattern includes a wildcard.
try {
@@ -1501,14 +1502,14 @@ public class Storage {
// TODO something unexpected happened; log error and return nothing
// Bundle b = context == null ? null : context.getBundle();
// eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e);
- return pathList;
+ return new ArrayList<String>(pathList);
}
}
// find the entry paths for the datas
for (BundleFile bundleFile : bundleFiles) {
listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList);
}
- return pathList;
+ return new ArrayList<String>(pathList);
}
public static String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException {
@@ -1551,10 +1552,16 @@ public class Storage {
return buffer == null ? filePattern : buffer.toString();
}
- private static List<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, List<String> pathList) {
+ // Use LinkedHashSet for optimized performance of contains() plus ordering
+ // guarantees.
+ private static LinkedHashSet<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, LinkedHashSet<String> pathList) {
if (pathList == null)
- pathList = new ArrayList<String>();
- Enumeration<String> entryPaths = bundleFile.getEntryPaths(path);
+ pathList = new LinkedHashSet<String>();
+ Enumeration<String> entryPaths;
+ if ((options & BundleWiring.FINDENTRIES_RECURSE) != 0)
+ entryPaths = bundleFile.getEntryPaths(path, true);
+ else
+ entryPaths = bundleFile.getEntryPaths(path);
if (entryPaths == null)
return pathList;
while (entryPaths.hasMoreElements()) {
@@ -1582,9 +1589,6 @@ public class Storage {
// prevent duplicates and match on the patternFilter
if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps)))
pathList.add(entry);
- // recurse only into entries that are directories
- if (((options & BundleWiring.FINDENTRIES_RECURSE) != 0) && !entry.equals(path) && entry.length() > 0 && lastSlash == (entry.length() - 1))
- listEntryPaths(bundleFile, entry, patternFilter, patternProps, options, pathList);
}
return pathList;
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java
index c755244..002ab37 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/SystemBundleFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2012 IBM Corporation and others.
+ * Copyright (c) 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -63,7 +63,7 @@ public class SystemBundleFile extends BundleFile {
}
@Override
- public Enumeration<String> getEntryPaths(String path) {
+ public Enumeration<String> getEntryPaths(String path, boolean recurse) {
return null;
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java
index 7930b86..735a6b2 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2012 IBM Corporation and others.
+ * Copyright (c) 2004, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -21,7 +21,6 @@ import org.eclipse.osgi.storage.StorageUtil;
* <p>
* Clients may extend this class.
* </p>
- * @since 3.2
*/
public abstract class BundleEntry {
protected static final int BUF_SIZE = 8 * 1024;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java
index 69d27fa..e4ddde7 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2004, 2012 IBM Corporation and others.
+ * Copyright (c) 2004, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -25,10 +25,10 @@ import org.eclipse.osgi.storage.url.bundleresource.Handler;
/**
* The BundleFile API is used by Adaptors to read resources out of an
* installed Bundle in the Framework.
- * <p>
- * Clients may extend this class.
- * </p>
- * @since 3.2
+ * <p/>
+ * Clients wishing to modify or extend the functionality of this class at
+ * runtime should extend the associated {@link BundleFileWrapper decorator}
+ * instead.
*/
abstract public class BundleFile {
static final SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
@@ -67,6 +67,18 @@ abstract public class BundleFile {
abstract public BundleEntry getEntry(String path);
/**
+ * Performs the same function as calling
+ * {@link #getEntryPaths(String, boolean)} with <code>recurse</code> equal
+ * to <code>false</code>.
+ * @param path path of the entry to locate in the bundle
+ * @return an Enumeration of Strings that indicate the paths found or
+ * null if the path does not exist.
+ */
+ public Enumeration<String> getEntryPaths(String path) {
+ return getEntryPaths(path, false);
+ }
+
+ /**
* Allows to access the entries of the bundle.
* Since the bundle content is usually a jar, this
* allows to access the jar contents.
@@ -77,10 +89,14 @@ abstract public class BundleFile {
* themselves. If a returned name is a directory, it finishes with a
* slash. If a returned name is a file, it does not finish with a slash.
* @param path path of the entry to locate in the bundle
+ * @param recurse - If <code>true</code>, provide entries for the files and
+ * directories within the directory denoted by <code>path</code> plus
+ * all sub-directories and files; otherwise, provide only the entries
+ * within the immediate directory.
* @return an Enumeration of Strings that indicate the paths found or
* null if the path does not exist.
*/
- abstract public Enumeration<String> getEntryPaths(String path);
+ abstract public Enumeration<String> getEntryPaths(String path, boolean recurse);
/**
* Closes the BundleFile.
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapper.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapper.java
new file mode 100755
index 0000000..33f5938
--- /dev/null
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapper.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2013 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.osgi.storage.bundlefile;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Enumeration;
+import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
+import org.eclipse.osgi.storage.BundleInfo;
+
+/**
+ * A {@link BundleFile bundle file} decorator.
+ * <p/>
+ * Clients wishing to modify or extend the behavior of a bundle file at runtime
+ * should extend this class instead. A hook is provided by the related {@link
+ * BundleFileWrapperFactoryHook abstract factory} class in response to a
+ * {@link BundleFileWrapperFactoryHook#wrapBundleFile(BundleFile,
+ * BundleInfo.Generation, boolean) call} from the framework.
+ */
+public class BundleFileWrapper extends BundleFile {
+ private final BundleFile bundleFile;
+
+ /**
+ * Creates a new <code>BundleFileWrapper</code> instance wrapping the
+ * given {@link BundleFile bundle file}.
+ *
+ * @param bundleFile - The bundle file to wrap.
+ * @throws NullPointerException - If the bundle file is <code>null</code>.
+ */
+ public BundleFileWrapper(BundleFile bundleFile) {
+ super(bundleFile.getBaseFile());
+ this.bundleFile = bundleFile;
+ }
+
+ @Override
+ public File getFile(String path, boolean nativeCode) {
+ return bundleFile.getFile(path, nativeCode);
+ }
+
+ @Override
+ public BundleEntry getEntry(String path) {
+ return bundleFile.getEntry(path);
+ }
+
+ @Override
+ public Enumeration<String> getEntryPaths(String path) {
+ return bundleFile.getEntryPaths(path);
+ }
+
+ @Override
+ public Enumeration<String> getEntryPaths(String path, boolean recurse) {
+ return bundleFile.getEntryPaths(path, recurse);
+ }
+
+ /**
+ * Get the wrapped bundle file.
+ *
+ * @return The wrapped bundle file.
+ */
+ public BundleFile getBundleFile() {
+ return bundleFile;
+ }
+
+ @Override
+ public void close() throws IOException {
+ bundleFile.close();
+ }
+
+ @Override
+ public void open() throws IOException {
+ bundleFile.open();
+ }
+
+ @Override
+ public boolean containsDir(String dir) {
+ return bundleFile.containsDir(dir);
+ }
+}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java
index 3edf2ea..6ad57ad 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/BundleFileWrapperChain.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2012 IBM Corporation and others.
+ * Copyright (c) 2008, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -11,59 +11,23 @@
package org.eclipse.osgi.storage.bundlefile;
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Enumeration;
-import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.internal.hookregistry.BundleFileWrapperFactoryHook;
/**
* Used to chain the BundleFile objects returned from {@link BundleFileWrapperFactoryHook}.
* This class is useful for traversing the chain of wrapped bundle files.
*/
-public class BundleFileWrapperChain extends BundleFile {
+public class BundleFileWrapperChain extends BundleFileWrapper {
private final BundleFile wrapped;
private final BundleFileWrapperChain next;
public BundleFileWrapperChain(BundleFile wrapped, BundleFileWrapperChain next) {
- super(null);
+ super(wrapped);
this.wrapped = wrapped;
this.next = next;
}
- public void close() throws IOException {
- wrapped.close();
- }
-
- public boolean containsDir(String dir) {
- return wrapped.containsDir(dir);
- }
-
- public BundleEntry getEntry(String path) {
- return wrapped.getEntry(path);
- }
-
- public Enumeration<String> getEntryPaths(String path) {
- return wrapped.getEntryPaths(path);
- }
-
- public File getFile(String path, boolean nativeCode) {
- return wrapped.getFile(path, nativeCode);
- }
-
- public void open() throws IOException {
- wrapped.open();
- }
-
- public File getBaseFile() {
- return wrapped.getBaseFile();
- }
-
- public URL getResourceURL(String path, Module hostModule, int index) {
- return wrapped.getResourceURL(path, hostModule, index);
- }
-
+ @Override
public String toString() {
return wrapped.toString();
}
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java
index da8c151..462892c 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirBundleFile.java
@@ -13,14 +13,12 @@ package org.eclipse.osgi.storage.bundlefile;
import java.io.File;
import java.io.IOException;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
+import java.util.*;
import org.eclipse.osgi.storage.StorageMsg;
import org.eclipse.osgi.util.NLS;
/**
* A BundleFile that uses a directory as its base file.
- * @since 3.2
*/
public class DirBundleFile extends BundleFile {
@@ -116,35 +114,29 @@ public class DirBundleFile extends BundleFile {
return dirPath != null && BundleFile.secureAction.isDirectory(dirPath);
}
- public Enumeration<String> getEntryPaths(String path) {
+ public Enumeration<String> getEntryPaths(String path, boolean recurse) {
if (path.length() > 0 && path.charAt(0) == '/')
path = path.substring(1);
- final File pathFile = getFile(path, false);
+ File pathFile = getFile(path, false);
if (pathFile == null || !BundleFile.secureAction.isDirectory(pathFile))
return null;
- final String[] fileList = BundleFile.secureAction.list(pathFile);
+ String[] fileList = BundleFile.secureAction.list(pathFile);
if (fileList == null || fileList.length == 0)
return null;
- final String dirPath = path.length() == 0 || path.charAt(path.length() - 1) == '/' ? path : path + '/';
- return new Enumeration<String>() {
- int cur = 0;
-
- public boolean hasMoreElements() {
- return fileList != null && cur < fileList.length;
- }
-
- public String nextElement() {
- if (!hasMoreElements()) {
- throw new NoSuchElementException();
- }
- java.io.File childFile = new java.io.File(pathFile, fileList[cur]);
- StringBuffer sb = new StringBuffer(dirPath).append(fileList[cur++]);
- if (BundleFile.secureAction.isDirectory(childFile)) {
- sb.append("/"); //$NON-NLS-1$
- }
- return sb.toString();
+ String dirPath = path.length() == 0 || path.charAt(path.length() - 1) == '/' ? path : path + '/';
+
+ LinkedHashSet<String> entries = new LinkedHashSet<String>();
+ for (String s : fileList) {
+ java.io.File childFile = new java.io.File(pathFile, s);
+ StringBuilder sb = new StringBuilder(dirPath).append(s);
+ if (BundleFile.secureAction.isDirectory(childFile)) {
+ sb.append("/"); //$NON-NLS-1$
+ if (recurse)
+ entries.addAll(Collections.list(getEntryPaths(sb.toString(), true)));
}
- };
+ entries.add(sb.toString());
+ }
+ return Collections.enumeration(entries);
}
public void close() {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java
index 0bb1cee..a4a7d26 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/DirZipBundleEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2012 IBM Corporation and others.
+ * Copyright (c) 2005, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,7 +19,6 @@ import java.net.URL;
* Represents a directory entry in a ZipBundleFile. This object is used to
* reference a directory entry in a ZipBundleFile when the directory entries are
* not included in the zip file.
- * @since 3.2
*/
public class DirZipBundleEntry extends BundleEntry {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java
index 94bc8ee..8a4f00a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/FileBundleEntry.java
@@ -18,7 +18,6 @@ import java.net.URL;
/**
* A BundleEntry represented by a File object. The FileBundleEntry class is
* used for bundles that are installed as extracted zips on a file system.
- * @since 3.2
*/
public class FileBundleEntry extends BundleEntry {
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java
index fcf148f..06885d5 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/MRUBundleFileList.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2012 IBM Corporation and others.
+ * Copyright (c) 2005, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -20,7 +20,6 @@ import org.eclipse.osgi.framework.eventmgr.*;
* track of open BundleFiles. The MRU will use the file limit specified by the property
* &quot;osgi.bundlefile.limit&quot; by default unless the MRU is constructed with a specific
* file limit.
- * @since 3.2
*/
public class MRUBundleFileList implements EventDispatcher<Object, Object, BundleFile> {
private static final int MIN = 10;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java
index dea0669..7184414 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/NestedDirBundleFile.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2012 IBM Corporation and others.
+ * Copyright (c) 2005, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -25,7 +25,6 @@ import java.util.Enumeration;
* <pre>
* Bundle-ClassPath: nested.jar,nesteddir/
* </pre>
- * @since 3.2
*/
public class NestedDirBundleFile extends BundleFile {
private final BundleFile baseBundleFile;
@@ -66,8 +65,8 @@ public class NestedDirBundleFile extends BundleFile {
return new StringBuffer(cp).append(path).toString();
}
- public Enumeration<String> getEntryPaths(String path) {
- final Enumeration<String> basePaths = baseBundleFile.getEntryPaths(prependNestedDir(path));
+ public Enumeration<String> getEntryPaths(String path, boolean recurse) {
+ final Enumeration<String> basePaths = baseBundleFile.getEntryPaths(prependNestedDir(path), recurse);
final int cpLength = cp.length();
if (basePaths == null)
return null;
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java
index 727e59d..2c8671a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleEntry.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2012 IBM Corporation and others.
+ * Copyright (c) 2005, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -19,7 +19,6 @@ import java.util.zip.ZipEntry;
/**
* A BundleEntry represented by a ZipEntry in a ZipFile. The ZipBundleEntry
* class is used for bundles that are installed as a ZipFile on a file system.
- * @since 3.2
*/
public class ZipBundleEntry extends BundleEntry {
/**
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java
index d8f796a..eb291d8 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/storage/bundlefile/ZipBundleFile.java
@@ -24,7 +24,6 @@ import org.eclipse.osgi.util.NLS;
/**
* A BundleFile that uses a ZipFile as it base file.
- * @since 3.2
*/
public class ZipBundleFile extends BundleFile {
@@ -255,39 +254,55 @@ public class ZipBundleFile extends BundleFile {
}
- public synchronized Enumeration<String> getEntryPaths(String path) {
- if (!checkedOpen())
- return null;
+ @Override
+ public synchronized Enumeration<String> getEntryPaths(String path, boolean recurse) {
if (path == null)
throw new NullPointerException();
+ // Is the zip file already open or, if not, can it be opened?
+ if (!checkedOpen())
+ return null;
+ // Strip any leading '/' off of path.
if (path.length() > 0 && path.charAt(0) == '/')
path = path.substring(1);
+ // Append a '/', if not already there, to path if not an empty string.
if (path.length() > 0 && path.charAt(path.length() - 1) != '/')
- path = new StringBuffer(path).append("/").toString(); //$NON-NLS-1$
+ path = new StringBuilder(path).append("/").toString(); //$NON-NLS-1$
- List<String> vEntries = new ArrayList<String>();
+ Set<String> vEntries = new HashSet<String>();
+ // Get all zip file entries and add the ones of interest.
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry zipEntry = entries.nextElement();
String entryPath = zipEntry.getName();
+ // Is the entry of possible interest? Note that
+ // string.startsWith("") == true.
if (entryPath.startsWith(path)) {
+ // If we get here, we know that the entry is either (1) equal to
+ // path, (2) a file under path, or (3) a subdirectory of path.
if (path.length() < entryPath.length()) {
- if (entryPath.lastIndexOf('/') < path.length()) {
- vEntries.add(entryPath);
- } else {
- entryPath = entryPath.substring(path.length());
- int slash = entryPath.indexOf('/');
- entryPath = path + entryPath.substring(0, slash + 1);
- if (!vEntries.contains(entryPath))
- vEntries.add(entryPath);
- }
+ // If we get here, we know that entry is not equal to path.
+ getEntryPaths(path, entryPath.substring(path.length()), recurse, vEntries);
}
}
}
return vEntries.size() == 0 ? null : Collections.enumeration(vEntries);
}
+ private void getEntryPaths(String path, String entry, boolean recurse, Set<String> entries) {
+ if (entry.length() == 0)
+ return;
+ int slash = entry.indexOf('/');
+ if (slash == -1)
+ entries.add(path + entry);
+ else {
+ path = path + entry.substring(0, slash + 1);
+ entries.add(path);
+ if (recurse)
+ getEntryPaths(path, entry.substring(slash + 1), true, entries);
+ }
+ }
+
public synchronized void close() throws IOException {
if (!closed) {
if (referenceCount > 0 && isMruListClosing()) {