summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRadoslav Ivanov2012-06-05 14:30:22 (EDT)
committer Violeta Georgieva2012-06-05 14:30:22 (EDT)
commit1e1f581a359fc082222cf5f2d70c61a62a9c6a19 (patch)
tree76de9b1ef03739645c0eae96c15403d3ac76d9aa
parent62793778a6e0ebe6d53dab5a7439596c100c72d3 (diff)
downloadorg.eclipse.gemini.web.gemini-web-container-1e1f581a359fc082222cf5f2d70c61a62a9c6a19.zip
org.eclipse.gemini.web.gemini-web-container-1e1f581a359fc082222cf5f2d70c61a62a9c6a19.tar.gz
org.eclipse.gemini.web.gemini-web-container-1e1f581a359fc082222cf5f2d70c61a62a9c6a19.tar.bz2
bug 379112: If possible cache all zip entries of the war file. Use ZipFile.getInputStream(ZipEntry) instead of opening the war file for every nested jar that has to be scanned. Do not scan for classes if the notification fo classes is disabled.
-rw-r--r--org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleScanner.java94
-rw-r--r--org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleScannerTests.java101
2 files changed, 137 insertions, 58 deletions
diff --git a/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleScanner.java b/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleScanner.java
index bbdb962..a7cc911 100644
--- a/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleScanner.java
+++ b/org.eclipse.gemini.web.core/src/main/java/org/eclipse/gemini/web/internal/url/WebBundleScanner.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 VMware Inc.
+ * Copyright (c) 2009, 2012 VMware Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -19,21 +19,26 @@ package org.eclipse.gemini.web.internal.url;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
+import java.net.URLDecoder;
+import java.util.Collection;
+import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+import org.eclipse.virgo.util.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.eclipse.virgo.util.io.IOUtils;
-
final class WebBundleScanner {
private static final Logger LOGGER = LoggerFactory.getLogger(WebBundleScanner.class);
@@ -60,6 +65,10 @@ final class WebBundleScanner {
private final URL source;
+ private final String localSourcePath;
+
+ private final Collection<ZipEntry> sourceZipEntries = new HashSet<ZipEntry>();
+
private final WebBundleScannerCallback callBack;
private final boolean findClassesInNestedJars;
@@ -81,6 +90,7 @@ final class WebBundleScanner {
this.source = source;
this.callBack = callBack;
this.findClassesInNestedJars = findClassesInNestedJars;
+ this.localSourcePath = getLocalSourcePath(source);
}
/**
@@ -92,6 +102,7 @@ final class WebBundleScanner {
void scanWar() throws IOException {
synchronized (this.monitor) {
this.scannedJars.clear();
+ this.sourceZipEntries.clear();
if (isDirectory()) {
scanWarDirectory();
} else {
@@ -209,11 +220,13 @@ final class WebBundleScanner {
}
}
- JarEntry entry;
- while ((entry = jis.getNextJarEntry()) != null) {
- String entryName = entry.getName();
- if (entryName.endsWith(CLASS_SUFFIX)) {
- notifyClassFound(entryName);
+ if (this.findClassesInNestedJars) {
+ JarEntry entry;
+ while ((entry = jis.getNextJarEntry()) != null) {
+ String entryName = entry.getName();
+ if (entryName.endsWith(CLASS_SUFFIX)) {
+ notifyClassFound(entryName);
+ }
}
}
}
@@ -247,7 +260,23 @@ final class WebBundleScanner {
}
}
- private void scanNestedJarInWarFile(String jarPath) throws IOException {
+ private void scanNestedJarInWarFile(final String jarPath) throws IOException {
+ if (this.localSourcePath == null) {
+ scanNestedJarInWarFileWithStream(jarPath);
+ return;
+ }
+
+ scanNestedJarInWarFileWithZipFile(jarPath, this.localSourcePath);
+ }
+
+ private String getLocalSourcePath(final URL url) {
+ if (!FILE_SCHEME.equals(url.getProtocol())) {
+ return null;
+ }
+ return URLDecoder.decode(url.getPath());
+ }
+
+ private void scanNestedJarInWarFileWithStream(String jarPath) throws IOException {
JarInputStream jis = new JarInputStream(this.source.openStream());
try {
JarEntry entry;
@@ -263,13 +292,54 @@ final class WebBundleScanner {
} finally {
IOUtils.closeQuietly(jis);
}
+ }
+
+ private void scanNestedJarInWarFileWithZipFile(String jarPath, String localSourcePath) throws IOException {
+ JarFile jarFile = null;
+ try {
+ InputStream foundInputStream = null;
+ String foundZipEntryName = null;
+ if (this.sourceZipEntries.isEmpty()) {// then search and cache all entries
+ jarFile = new JarFile(localSourcePath);
+ Enumeration<JarEntry> jarFileEntries = jarFile.entries();
+ while (jarFileEntries.hasMoreElements()) {
+ final ZipEntry zipEntry = jarFileEntries.nextElement();
+ // 1. cache
+ this.sourceZipEntries.add(zipEntry);
+ // 2. search if it is not found still
+ if (foundZipEntryName == null && jarPath.endsWith(zipEntry.getName())) {
+ foundZipEntryName = zipEntry.getName();
+ foundInputStream = jarFile.getInputStream(zipEntry);
+ }
+ }
+ } else {// search entry in cache
+ for (ZipEntry zipEntry : this.sourceZipEntries) {
+ if (jarPath.endsWith(zipEntry.getName())) {
+ jarFile = new JarFile(localSourcePath);
+ foundZipEntryName = zipEntry.getName();
+ foundInputStream = jarFile.getInputStream(zipEntry);
+ break;
+ }
+
+ }
+ }
+ if (foundZipEntryName != null && driveCallBackIfNewJarFound(foundZipEntryName)) {
+ JarInputStream nestedJis = new JarInputStream(foundInputStream);
+ doScanNestedJar(foundZipEntryName, nestedJis);
+ }
+ } finally {// quiet close
+ if (jarFile != null) {
+ try {
+ jarFile.close();
+ } catch (IOException _) {
+ }
+ }
+ }
}
private void notifyClassFound(String entryName) {
- if (this.findClassesInNestedJars) {
- this.callBack.classFound(entryName);
- }
+ this.callBack.classFound(entryName);
}
private boolean isDirectory() {
diff --git a/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleScannerTests.java b/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleScannerTests.java
index 7d5ea97..32316e0 100644
--- a/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleScannerTests.java
+++ b/org.eclipse.gemini.web.core/src/test/java/org/eclipse/gemini/web/internal/url/WebBundleScannerTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 VMware Inc.
+ * Copyright (c) 2009, 2012 VMware Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
@@ -21,38 +21,49 @@ import static org.easymock.EasyMock.verify;
import java.io.File;
import java.io.IOException;
+import java.net.URL;
import org.easymock.EasyMock;
-import org.junit.Test;
-
-import org.eclipse.gemini.web.internal.url.WebBundleScanner;
-import org.eclipse.gemini.web.internal.url.WebBundleScannerCallback;
import org.eclipse.virgo.util.io.JarUtils;
import org.eclipse.virgo.util.io.PathReference;
+import org.junit.Test;
public class WebBundleScannerTests {
- private static final File WAR_FILE = new File("target/resources/simple-war.war");
+ private static final File WAR_FILE = new File("target/resources/simple-war.war");
+
+ private static final File WAR_CLASSPATHDEPS = new File("../org.eclipse.gemini.web.test/src/test/resources/classpathdeps.war");
+
+ @Test
+ public void testScanClasspathDeps() throws IOException {
+ final WebBundleScannerCallback callback = EasyMock.createMock(WebBundleScannerCallback.class);
+
+ setExpectationsClasspathDeps(callback);
+
+ scan(WAR_CLASSPATHDEPS.toURI().toURL(), callback);
+ }
@Test
public void testScanLib() throws IOException {
WebBundleScannerCallback callback = EasyMock.createMock(WebBundleScannerCallback.class);
-
+
setExpectations(callback);
-
- replay(callback);
-
- WebBundleScanner scanner = new WebBundleScanner(WAR_FILE.toURI().toURL(), callback);
- scanner.scanWar();
-
- verify(callback);
+
+ scan(WAR_FILE.toURI().toURL(), callback);
+ }
+
+ private void setExpectationsClasspathDeps(WebBundleScannerCallback callback) {
+ callback.jarFound("WEB-INF/lib/jar1.jar");
+ callback.jarFound("j2/jar2.jar");
+ callback.jarFound("j3/jar3.jar");
+ callback.jarFound("j4/jar4.jar");
}
-
+
private void setExpectations(WebBundleScannerCallback callback) {
- callback.jarFound("WEB-INF/lib/com.springsource.slf4j.api-1.6.1.jar");
+ callback.jarFound("WEB-INF/lib/com.springsource.slf4j.api-1.6.1.jar");
callback.classFound("foo/bar/Doo.class");
}
-
+
private void setExpectationsIncludingNestedJars(WebBundleScannerCallback callback) {
setExpectations(callback);
@@ -80,61 +91,59 @@ public class WebBundleScannerTests {
callback.classFound("org/slf4j/spi/MarkerFactoryBinder.class");
callback.classFound("org/slf4j/spi/MDCAdapter.class");
}
-
+
@SuppressWarnings("deprecation")
@Test
public void testScanLibIncludingNestedJars() throws IOException {
-
+
WebBundleScannerCallback callback = EasyMock.createMock(WebBundleScannerCallback.class);
-
+
setExpectationsIncludingNestedJars(callback);
-
- replay(callback);
-
- WebBundleScanner scanner = new WebBundleScanner(WAR_FILE.toURL(), callback, true);
- scanner.scanWar();
-
- verify(callback);
+
+ scan(WAR_FILE.toURL(), callback, true);
}
-
+
@Test
public void testScanDir() throws Exception {
PathReference pr = unpackToDir();
try {
WebBundleScannerCallback callback = EasyMock.createMock(WebBundleScannerCallback.class);
-
+
setExpectations(callback);
-
- replay(callback);
-
- WebBundleScanner scanner = new WebBundleScanner(pr.toURI().toURL(), callback);
- scanner.scanWar();
-
- verify(callback);
+
+ scan(pr.toURI().toURL(), callback);
} finally {
pr.delete(true);
}
}
-
+
@Test
public void testScanDirIncludingNestedJars() throws Exception {
PathReference pr = unpackToDir();
try {
WebBundleScannerCallback callback = EasyMock.createMock(WebBundleScannerCallback.class);
-
+
setExpectationsIncludingNestedJars(callback);
-
- replay(callback);
-
- WebBundleScanner scanner = new WebBundleScanner(pr.toURI().toURL(), callback, true);
- scanner.scanWar();
-
- verify(callback);
+
+ scan(pr.toURI().toURL(), callback, true);
} finally {
pr.delete(true);
}
}
-
+
+ private void scan(final URL url, final WebBundleScannerCallback callback) throws IOException {
+ this.scan(url, callback, false);
+ }
+
+ private void scan(final URL url, final WebBundleScannerCallback callback, final boolean findClassesInNestedJars) throws IOException {
+ replay(callback);
+
+ final WebBundleScanner scanner = new WebBundleScanner(url, callback, findClassesInNestedJars);
+ scanner.scanWar();
+
+ verify(callback);
+ }
+
private PathReference unpackToDir() throws IOException {
String tmpDir = System.getProperty("java.io.tmpdir");
PathReference dest = new PathReference(new File(tmpDir, "unpack-" + System.currentTimeMillis()));