Bug 490004: [null][impl] unassigned variable annotationZip in
ClassFile.getJarBinaryTypeInfo()

Change-Id: I70b8c97b0cb3e088ec8a8a6aaa1e3310d7edf23b
Signed-off-by: Stephan Herrmann <stephan.herrmann@berlin.de>
diff --git a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
index 07e3a1b..9dde6bd 100644
--- a/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
+++ b/org.eclipse.jdt.core/batch/org/eclipse/jdt/internal/compiler/batch/FileSystem.java
@@ -270,17 +270,23 @@
 			Classpath classpathEntry = this.classpaths[i];
 			if (classpathEntry.hasAnnotationFileFor(qualifiedTypeName)) {
 				// in case of 'this.annotationsFromClasspath' we indeed search for .eea entries inside the main zipFile of the entry:
-				@SuppressWarnings("resource")
 				ZipFile zip = classpathEntry instanceof ClasspathJar ? ((ClasspathJar) classpathEntry).zipFile : null;
+				boolean shouldClose = false; // don't close classpathEntry.zipFile, which we don't own
 				try {
 					if (zip == null) {
 						zip = ExternalAnnotationDecorator.getAnnotationZipFile(classpathEntry.getPath(), null);
+						shouldClose = true;
 					}
 					answer.setBinaryType(ExternalAnnotationDecorator.create(answer.getBinaryType(), classpathEntry.getPath(), 
 							qualifiedTypeName, zip));
 					break;
 				} catch (IOException e) {
 					// ignore broken entry, keep searching
+				} finally {
+					if (shouldClose && zip != null)
+						try {
+							zip.close();
+						} catch (IOException e) { /* nothing */ }
 				}
 			}
 		}
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
index d37d74d..cee25a9 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java
@@ -362,9 +362,6 @@
 	}
 
 	// TODO(sxenos): setup the external annotation provider if the IBinaryType came from the index
-	// TODO(sxenos): the old code always passed null as the third argument to setupExternalAnnotationProvider,
-	// but this looks like a bug. I've preserved it for now but we need to figure out what was supposed to go
-	// there.
 	PackageFragment pkg = (PackageFragment) getParent();
 	IJavaElement grandparent = pkg.getParent();
 	if (grandparent instanceof JarPackageFragmentRoot) {
@@ -379,7 +376,7 @@
 				IProject project = javaProject.getProject();
 				IPath externalAnnotationPath = ClasspathEntry.getExternalAnnotationPath(entry, project, false); // unresolved for use in ExternalAnnotationTracker
 				if (externalAnnotationPath != null) {
-					result = setupExternalAnnotationProvider(project, externalAnnotationPath, null, result, 
+					result = setupExternalAnnotationProvider(project, externalAnnotationPath, result, 
 						entryName.substring(0, entryName.length() - SuffixConstants.SUFFIX_CLASS.length));
 				} else if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) {
 					result = new ExternalAnnotationDecorator(result, true);
@@ -392,7 +389,7 @@
 }
 
 private IBinaryType setupExternalAnnotationProvider(IProject project, final IPath externalAnnotationPath,
-		ZipFile annotationZip, IBinaryType reader, final String typeName)
+		IBinaryType reader, final String typeName)
 {
 	IBinaryType result = reader;
 	// try resolve path within the workspace:
@@ -416,17 +413,16 @@
 	} else {
 		resolvedPath = externalAnnotationPath.toString(); // not in workspace, use as is
 	}
+	ZipFile annotationZip = null;
 	try {
-		if (annotationZip == null) {
-			annotationZip = ExternalAnnotationDecorator.getAnnotationZipFile(resolvedPath, new ExternalAnnotationDecorator.ZipFileProducer() {
-				@Override public ZipFile produce() throws IOException {
-					try {
-						return JavaModelManager.getJavaModelManager().getZipFile(externalAnnotationPath); // use (absolute, but) unresolved path here
-					} catch (CoreException e) {
-						throw new IOException("Failed to read annotation file for "+typeName+" from "+externalAnnotationPath.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
-					}
-				}});
-		}
+		annotationZip = ExternalAnnotationDecorator.getAnnotationZipFile(resolvedPath, new ExternalAnnotationDecorator.ZipFileProducer() {
+			@Override public ZipFile produce() throws IOException {
+				try {
+					return JavaModelManager.getJavaModelManager().getZipFile(externalAnnotationPath); // use (absolute, but) unresolved path here
+				} catch (CoreException e) {
+					throw new IOException("Failed to read annotation file for "+typeName+" from "+externalAnnotationPath.toString(), e); //$NON-NLS-1$ //$NON-NLS-2$
+				}
+			}});
 
 		ExternalAnnotationProvider annotationProvider = ExternalAnnotationDecorator
 				.externalAnnotationProvider(resolvedPath, typeName, annotationZip);
@@ -434,6 +430,9 @@
 	} catch (IOException e) {
 		Util.log(e);
 		return result;
+	} finally {
+		if (annotationZip != null)
+			JavaModelManager.getJavaModelManager().closeZipFile(annotationZip);
 	}
 	if (annotationZip == null) {
 		// Additional change listening for individual types only when annotations are in individual files.