[r302] Bug 82891 - Source lookup based upon the classpath info stored in manifest file in a JAR
diff --git a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardSourcePathProvider.java b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardSourcePathProvider.java index 4ea31e9..65243a5 100644 --- a/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardSourcePathProvider.java +++ b/org.eclipse.jdt.launching/launching/org/eclipse/jdt/launching/StandardSourcePathProvider.java
@@ -11,10 +11,16 @@ package org.eclipse.jdt.launching; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.debug.core.ILaunchConfiguration; import org.eclipse.jdt.internal.launching.DefaultProjectClasspathEntry; import org.eclipse.jdt.internal.launching.VariableClasspathEntry; @@ -67,10 +73,13 @@ } else if (typeId.equals(VariableClasspathEntry.TYPE_ID)) { // add the archive itself - we currently do not allow a source attachment res = JavaRuntime.resolveRuntimeClasspathEntry(entry, configuration); - } + } else { + res = JavaRuntime.resolveRuntimeClasspathEntry(entry, configuration); + } if (res != null) { for (int j = 0; j < res.length; j++) { all.add(res[j]); + addManifestReferences(res[j], all); } } break; @@ -78,6 +87,7 @@ IRuntimeClasspathEntry[] resolved =JavaRuntime.resolveRuntimeClasspathEntry(entries[i], configuration); for (int j = 0; j < resolved.length; j++) { all.add(resolved[j]); + addManifestReferences(resolved[j], all); } break; } @@ -85,4 +95,51 @@ return (IRuntimeClasspathEntry[])all.toArray(new IRuntimeClasspathEntry[all.size()]); } + /** + * If the given entry is an archive, adds any archives referenced by the associated manifest. + * + * @param entry runtime classpath entry + * @param all list to add references to + */ + protected void addManifestReferences(IRuntimeClasspathEntry entry, List all) { + if (entry.getType() == IRuntimeClasspathEntry.ARCHIVE) { + String location = entry.getLocation(); + if (location != null) { + JarFile jar = null; + try { + jar = new JarFile(location); + Manifest manifest = jar.getManifest(); + if (manifest != null) { + Attributes mainAttributes = manifest.getMainAttributes(); + if (mainAttributes != null) { + String value = mainAttributes.getValue(Attributes.Name.CLASS_PATH); + if (value != null) { + String[] entries = value.split("\\s+"); //$NON-NLS-1$ + IPath base = new Path(location); + base = base.removeLastSegments(1); + for (int i = 0; i < entries.length; i++) { + IPath path = base.append(entries[i]); + if (path.toFile().exists()) { + IRuntimeClasspathEntry ref = JavaRuntime.newArchiveRuntimeClasspathEntry(path); + if (!all.contains(ref)) { + all.add(ref); + } + } + } + } + } + } + } catch (IOException e) { + } finally { + if (jar != null) { + try { + jar.close(); + } catch (IOException e) { + } + } + } + } + } + } + }