### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/JavaModelManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java,v retrieving revision 1.426 diff -u -r1.426 JavaModelManager.java --- model/org/eclipse/jdt/internal/core/JavaModelManager.java 22 Jan 2009 09:46:59 -0000 1.426 +++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 29 Jan 2009 17:44:26 -0000 @@ -1126,6 +1126,9 @@ } public synchronized ClasspathChange resetResolvedClasspath() { + // clear non-chaining jars cache + JavaModelManager.getJavaModelManager().resetNonChainingJarsCache(); + // null out resolved information return setResolvedClasspath(null, null, null, null, this.rawTimeStamp); } @@ -1336,6 +1339,11 @@ private ThreadLocal zipFiles = new ThreadLocal(); private UserLibraryManager userLibraryManager; + + /* + * List of IPath of jars that are known to not contain a chaining (through MANIFEST.MF) to another library + */ + private HashSet nonChainingJars; /** * Update the classpath variable cache @@ -1461,6 +1469,7 @@ private JavaModelManager() { // singleton: prevent others from creating a new instance if (Platform.isRunning()) this.indexManager = new IndexManager(); + this.nonChainingJars = loadNonChainingJarsCache(); } /** @@ -1470,6 +1479,12 @@ options.put(JavaCore.COMPILER_PB_INVALID_IMPORT, JavaCore.ERROR); options.put(JavaCore.COMPILER_PB_UNREACHABLE_CODE, JavaCore.ERROR); } + + public void addNonChainingJar(IPath path) { + if (this.nonChainingJars == null) + return; + this.nonChainingJars.add(path); + } /** * Starts caching ZipFiles. @@ -2800,6 +2815,10 @@ return JavaCore.COMPILER_PB_INVALID_IMPORT.equals(optionName) || JavaCore.COMPILER_PB_UNREACHABLE_CODE.equals(optionName); } + + public boolean isNonChainingJar(IPath path) { + return this.nonChainingJars != null && this.nonChainingJars.contains(path); + } public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) { if (classpathIsResolved) { @@ -2808,6 +2827,57 @@ getClasspathBeingResolved().remove(project); } } + + private HashSet loadNonChainingJarsCache() { + HashSet nonChainingJarsCache = new HashSet(); + File nonChainingJarsFile = getNonChainingJarsFile(); + DataInputStream in = null; + try { + in = new DataInputStream(new BufferedInputStream(new FileInputStream(nonChainingJarsFile))); + int size = in.readInt(); + while (size-- > 0) { + String path = in.readUTF(); + nonChainingJarsCache.add(Path.fromPortableString(path)); + } + } catch (IOException e) { + if (nonChainingJarsFile.exists()) + Util.log(e, "Unable to read non-chaining jar cache file"); //$NON-NLS-1$ + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // nothing we can do: ignore + } + } + } + return nonChainingJarsCache; + } + + private File getNonChainingJarsFile() { + return JavaCore.getPlugin().getStateLocation().append("nonChainingJarsCache").toFile(); //$NON-NLS-1$ + } + + private HashSet getNonChainingJarsCache() throws CoreException { + if (this.nonChainingJars != null) + return this.nonChainingJars; + HashSet result = new HashSet(); + IJavaProject[] projects = getJavaModel().getJavaProjects(); + for (int i = 0, length = projects.length; i < length; i++) { + IJavaProject javaProject = projects[i]; + IClasspathEntry[] classpath = ((JavaProject) javaProject).getResolvedClasspath(); + for (int j = 0, length2 = classpath.length; j < length2; j++) { + IClasspathEntry entry = classpath[j]; + IPath path; + if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY + && !result.contains(path = entry.getPath()) + && ClasspathEntry.resolvedChainedLibraries(path).length == 0) { + result.add(path); + } + } + } + return result; + } public void loadVariablesAndContainers() throws CoreException { // backward compatibility, consider persistent property @@ -3524,6 +3594,10 @@ protected synchronized void resetJarTypeCache() { this.cache.resetJarTypeCache(); } + + public void resetNonChainingJarsCache() { + this.nonChainingJars = null; + } /* * Resets the temporary cache for newly created elements to null. @@ -3596,6 +3670,32 @@ } } + private void saveNonChainingJarsCache() throws CoreException { + File file = getNonChainingJarsFile(); + DataOutputStream out = null; + try { + out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file))); + HashSet nonChainingJarsCache = getNonChainingJarsCache(); + out.writeInt(nonChainingJarsCache.size()); + Iterator entries = nonChainingJarsCache.iterator(); + while (entries.hasNext()) { + IPath path = (IPath) entries.next(); + out.writeUTF(path.toPortableString()); + } + } catch (IOException e) { + IStatus status = new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, IStatus.ERROR, "Problems while saving non-chaining jar cache", e); //$NON-NLS-1$ + throw new CoreException(status); + } finally { + if (out != null) { + try { + out.close(); + } catch (IOException e) { + // nothing we can do: ignore + } + } + } + } + private void saveVariablesAndContainers(ISaveContext context) throws CoreException { File file = getVariableAndContainersFile(); DataOutputStream out = null; @@ -3849,6 +3949,9 @@ // save variable and container values on snapshot/full save saveVariablesAndContainers(context); + + // save non-chaining jar cache on snapshot/full save + saveNonChainingJarsCache(); if (VERBOSE) traceVariableAndContainers("Saved", start); //$NON-NLS-1$ Index: model/org/eclipse/jdt/internal/core/ClasspathEntry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java,v retrieving revision 1.112 diff -u -r1.112 ClasspathEntry.java --- model/org/eclipse/jdt/internal/core/ClasspathEntry.java 15 Jan 2009 14:21:10 -0000 1.112 +++ model/org/eclipse/jdt/internal/core/ClasspathEntry.java 29 Jan 2009 17:44:25 -0000 @@ -874,70 +874,82 @@ if (visited.contains( jarPath)) return; visited.add(jarPath); - Object target = JavaModel.getTarget(jarPath, true/*check existence, otherwise the manifest cannot be read*/); - if (target instanceof IFile || target instanceof File) { - JavaModelManager manager = JavaModelManager.getJavaModelManager(); - ZipFile zip = null; - BufferedReader reader = null; - try { - zip = manager.getZipFile(jarPath); - ZipEntry manifest = zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$ - if (manifest != null) { // non-null implies regular file - reader = new BufferedReader(new InputStreamReader(zip.getInputStream(manifest))); - ManifestAnalyzer analyzer = new ManifestAnalyzer(); - boolean success = analyzer.analyzeManifestContents(reader); - List calledFileNames = analyzer.getCalledFileNames(); - if (!success || analyzer.getClasspathSectionsCount() == 1 && calledFileNames == null) { - if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { - Util.verbose("Invalid Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ - } - return; - } else if (analyzer.getClasspathSectionsCount() > 1) { - if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { - Util.verbose("Multiple Class-Path headers in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ - } - return; - } - if (calledFileNames != null) { - Iterator calledFilesIterator = calledFileNames.iterator(); - IPath directoryPath = jarPath.removeLastSegments(1); - while (calledFilesIterator.hasNext()) { - String calledFileName = (String) calledFilesIterator.next(); - if (!directoryPath.isValidPath(calledFileName)) { - if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { - Util.verbose("Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ - } - } else { - IPath calledJar = directoryPath.append(new Path(calledFileName)); - resolvedChainedLibraries(calledJar, visited, result); - result.add(calledJar); - } - } + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + if (manager.isNonChainingJar(jarPath)) + return; + List calledFileNames = getCalledFileNames(jarPath); + if (calledFileNames == null) { + manager.addNonChainingJar(jarPath); + } else { + Iterator calledFilesIterator = calledFileNames.iterator(); + IPath directoryPath = jarPath.removeLastSegments(1); + while (calledFilesIterator.hasNext()) { + String calledFileName = (String) calledFilesIterator.next(); + if (!directoryPath.isValidPath(calledFileName)) { + if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { + Util.verbose("Invalid Class-Path entry " + calledFileName + " in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ //$NON-NLS-2$ } + } else { + IPath calledJar = directoryPath.append(new Path(calledFileName)); + resolvedChainedLibraries(calledJar, visited, result); + result.add(calledJar); } - } catch (CoreException e) { - // not a zip file + } + } + } + + private static List getCalledFileNames(IPath jarPath) { + Object target = JavaModel.getTarget(jarPath, true/*check existence, otherwise the manifest cannot be read*/); + if (!(target instanceof IFile || target instanceof File)) + return null; + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + ZipFile zip = null; + BufferedReader reader = null; + List calledFileNames = null; + try { + zip = manager.getZipFile(jarPath); + ZipEntry manifest = zip.getEntry("META-INF/MANIFEST.MF"); //$NON-NLS-1$ + if (manifest == null) + return null; + // non-null implies regular file + reader = new BufferedReader(new InputStreamReader(zip.getInputStream(manifest))); + ManifestAnalyzer analyzer = new ManifestAnalyzer(); + boolean success = analyzer.analyzeManifestContents(reader); + calledFileNames = analyzer.getCalledFileNames(); + if (!success || analyzer.getClasspathSectionsCount() == 1 && calledFileNames == null) { if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { - Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ - e.printStackTrace(); + Util.verbose("Invalid Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ } - } catch (IOException e) { - // not a zip file + return null; + } else if (analyzer.getClasspathSectionsCount() > 1) { if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { - Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ - e.printStackTrace(); + Util.verbose("Multiple Class-Path headers in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ } - } finally { - manager.closeZipFile(zip); - if (reader != null) { - try { - reader.close(); - } catch (IOException e) { - // best effort - } + return null; + } + } catch (CoreException e) { + // not a zip file + if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { + Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ + e.printStackTrace(); + } + } catch (IOException e) { + // not a zip file + if (JavaModelManager.CP_RESOLVE_VERBOSE_FAILURE) { + Util.verbose("Could not read Class-Path header in manifest of jar file: " + jarPath.toOSString()); //$NON-NLS-1$ + e.printStackTrace(); + } + } finally { + manager.closeZipFile(zip); + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + // best effort } } } + return calledFileNames; } /*