### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/ElementCache.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ElementCache.java,v retrieving revision 1.11 diff -u -r1.11 ElementCache.java --- model/org/eclipse/jdt/internal/core/ElementCache.java 2 Feb 2006 14:00:46 -0000 1.11 +++ model/org/eclipse/jdt/internal/core/ElementCache.java 7 Feb 2006 12:57:13 -0000 @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; -import java.text.NumberFormat; - import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.util.LRUCache; @@ -96,13 +94,4 @@ } } -public String toStringFillingRation(String cacheName) { - StringBuffer buffer = new StringBuffer(cacheName); - buffer.append('['); - buffer.append(getSpaceLimit()); - buffer.append("]: "); //$NON-NLS-1$ - buffer.append(NumberFormat.getInstance().format(fillingRatio())); - buffer.append("% full"); //$NON-NLS-1$ - return buffer.toString(); -} } Index: model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java,v retrieving revision 1.35 diff -u -r1.35 OverflowingLRUCache.java --- model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java 3 Feb 2006 14:35:59 -0000 1.35 +++ model/org/eclipse/jdt/internal/core/OverflowingLRUCache.java 7 Feb 2006 12:57:19 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; -import java.text.NumberFormat; import java.util.Enumeration; import java.util.Iterator; @@ -199,20 +198,6 @@ * Returns a new instance of the reciever. */ protected abstract LRUCache newInstance(int size, int overflow); - /** - * Answers the value in the cache at the given key. - * If the value is not in the cache, returns null - * - * This function does not modify timestamps. - */ - public Object peek(Object key) { - - LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key); - if (entry == null) { - return null; - } - return entry._fValue; - } /** * For testing purposes only */ @@ -413,8 +398,8 @@ */ public String toString() { return - "OverflowingLRUCache " + NumberFormat.getInstance().format(this.fillingRatio()) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$ - this.toStringContents(); + toStringFillingRation("OverflowingLRUCache ") + //$NON-NLS-1$ + toStringContents(); } /** * Updates the timestamp for the given entry, ensuring that the queue is Index: model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java,v retrieving revision 1.38 diff -u -r1.38 JavaProjectElementInfo.java --- model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java 11 Jan 2006 15:05:29 -0000 1.38 +++ model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java 7 Feb 2006 12:57:17 -0000 @@ -287,6 +287,7 @@ */ void resetCaches() { this.projectCache = null; + JavaModelManager.getJavaModelManager().resetJarTypeCache(); } /** Index: model/org/eclipse/jdt/internal/core/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java,v retrieving revision 1.118 diff -u -r1.118 ClassFile.java --- model/org/eclipse/jdt/internal/core/ClassFile.java 6 Feb 2006 12:54:25 -0000 1.118 +++ model/org/eclipse/jdt/internal/core/ClassFile.java 7 Feb 2006 12:57:13 -0000 @@ -174,6 +174,29 @@ public boolean exists() { return super.exists() && validateClassFile().isOK(); } +public boolean existsUsingJarTypeCache() { + if (getPackageFragmentRoot().isArchive()) { + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + IType type = getType(); + Object info = manager.getInfo(type); + if (info == JavaModelCache.NON_EXISTING_JAR_TYPE_INFO) + return false; + else if (info != null) + return true; + try { + info = getJarBinaryTypeInfo((PackageFragment) getParent()); + } catch (CoreException e) { + info = null; + } catch (IOException e) { + info = null; + } catch (ClassFormatException e) { + info = null; + } + manager.putJarTypeInfo(type, info == null ? JavaModelCache.NON_EXISTING_JAR_TYPE_INFO : info); + return info != null; + } else + return exists(); +} /** * Finds the deepest IJavaElement in the hierarchy of @@ -217,25 +240,10 @@ * or when this class file is not present in the JAR */ public IBinaryType getBinaryTypeInfo(IFile file) throws JavaModelException { - JavaElement le = (JavaElement) getParent(); - if (le instanceof JarPackageFragment) { + JavaElement pkg = (JavaElement) getParent(); + if (pkg instanceof JarPackageFragment) { try { - JarPackageFragmentRoot root = (JarPackageFragmentRoot) le.getParent(); - IBinaryType info = null; - ZipFile zip = null; - try { - zip = root.getJar(); - PackageFragment pkg = (PackageFragment) le; - String entryName = Util.concatWith(pkg.names, getElementName(), '/'); - ZipEntry ze = zip.getEntry(entryName); - if (ze != null) { - byte contents[] = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip); - String fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; - info = new ClassFileReader(contents, fileName.toCharArray(), true/*fully initialize so as to not keep a reference to the byte array*/); - } - } finally { - JavaModelManager.getJavaModelManager().closeZipFile(zip); - } + IBinaryType info = getJarBinaryTypeInfo((PackageFragment) pkg); if (info == null) { throw newNotPresentException(); } @@ -265,6 +273,23 @@ } } } +private IBinaryType getJarBinaryTypeInfo(PackageFragment pkg) throws CoreException, IOException, ClassFormatException { + JarPackageFragmentRoot root = (JarPackageFragmentRoot) pkg.getParent(); + ZipFile zip = null; + try { + zip = root.getJar(); + String entryName = Util.concatWith(pkg.names, getElementName(), '/'); + ZipEntry ze = zip.getEntry(entryName); + if (ze != null) { + byte contents[] = org.eclipse.jdt.internal.compiler.util.Util.getZipEntryByteContent(ze, zip); + String fileName = root.getHandleIdentifier() + IDependent.JAR_FILE_ENTRY_SEPARATOR + entryName; + return new ClassFileReader(contents, fileName.toCharArray(), true/*fully initialize so as to not keep a reference to the byte array*/); + } + } finally { + JavaModelManager.getJavaModelManager().closeZipFile(zip); + } + return null; +} public IBuffer getBuffer() throws JavaModelException { if (validateClassFile().isOK()) { return super.getBuffer(); Index: model/org/eclipse/jdt/internal/core/NameLookup.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/NameLookup.java,v retrieving revision 1.103 diff -u -r1.103 NameLookup.java --- model/org/eclipse/jdt/internal/core/NameLookup.java 1 Feb 2006 14:26:23 -0000 1.103 +++ model/org/eclipse/jdt/internal/core/NameLookup.java 7 Feb 2006 12:57:18 -0000 @@ -534,12 +534,6 @@ * Find secondary type for a project. */ private IType findSecondaryType(String packageName, String typeName, IJavaProject project, boolean waitForIndexes, IProgressMonitor monitor) { - if (VERBOSE) { - Util.verbose("NameLookup FIND SECONDARY TYPES:"); //$NON-NLS-1$ - Util.verbose(" -> pkg name: " + packageName); //$NON-NLS-1$ - Util.verbose(" -> type name: " + typeName); //$NON-NLS-1$ - Util.verbose(" -> project: "+project.getElementName()); //$NON-NLS-1$ - } JavaModelManager manager = JavaModelManager.getJavaModelManager(); try { IJavaProject javaProject = project; @@ -936,27 +930,24 @@ if (VERBOSE) start = System.currentTimeMillis(); try { - IClassFile[] classFiles= null; - try { - classFiles= pkg.getClassFiles(); - } catch (JavaModelException npe) { - return; // the package is not present - } - int length= classFiles.length; if (!partialMatch) { // exact match - for (int i= 0; i < length; i++) { - if (requestor.isCanceled()) return; - ClassFile classFile= (ClassFile) classFiles[i]; - if (name.equals(classFile.name)) { // ClassFile#name contains the name of the .class file without the .class extension - IType type = classFile.getType(); - if (acceptType(type, acceptFlags, false/*not a source type*/)) { - requestor.acceptType(type); - break; // since an exact match was requested, no other matching type can exist - } + if (requestor.isCanceled()) return; + ClassFile classFile = new ClassFile((PackageFragment) pkg, name); + if (classFile.existsUsingJarTypeCache()) { + IType type = classFile.getType(); + if (acceptType(type, acceptFlags, false/*not a source type*/)) { + requestor.acceptType(type); } } } else { + IClassFile[] classFiles= null; + try { + classFiles= pkg.getClassFiles(); + } catch (JavaModelException npe) { + return; // the package is not present + } + int length= classFiles.length; String unqualifiedName = name; int index = name.lastIndexOf('$'); if (index != -1) { Index: model/org/eclipse/jdt/internal/core/Openable.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java,v retrieving revision 1.109 diff -u -r1.109 Openable.java --- model/org/eclipse/jdt/internal/core/Openable.java 26 Jan 2006 11:28:29 -0000 1.109 +++ model/org/eclipse/jdt/internal/core/Openable.java 7 Feb 2006 12:57:18 -0000 @@ -237,7 +237,7 @@ JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().remove(this); if (JavaModelManager.VERBOSE) { - System.out.println(JavaModelManager.getJavaModelManager().cache.toStringFillingRation("-> ")); //$NON-NLS-1$ + System.out.println(JavaModelManager.getJavaModelManager().cacheToString("-> ")); //$NON-NLS-1$ } } /** Index: model/org/eclipse/jdt/internal/core/JavaModelCache.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelCache.java,v retrieving revision 1.25 diff -u -r1.25 JavaModelCache.java --- model/org/eclipse/jdt/internal/core/JavaModelCache.java 2 Feb 2006 14:00:46 -0000 1.25 +++ model/org/eclipse/jdt/internal/core/JavaModelCache.java 7 Feb 2006 12:57:14 -0000 @@ -13,6 +13,7 @@ import java.util.Map; import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.internal.core.util.LRUCache; /** * The cache of java elements to their respective info. @@ -26,6 +27,8 @@ public static final int DEFAULT_OPENABLE_SIZE = 500; // average 6629 bytes per openable (includes children) -> maximum size : 662900*BASE_VALUE bytes public static final int DEFAULT_CHILDREN_SIZE = 500*20; // average 20 children per openable + public static final Object NON_EXISTING_JAR_TYPE_INFO = new Object(); + /* * The memory ratio that should be applied to the above constants. */ @@ -61,6 +64,11 @@ */ protected Map childrenCache; + /* + * Cache of open binary type (inside a jar) that have a non-open parent + */ + protected LRUCache jarTypeCache; + public JavaModelCache() { // set the size of the caches in function of the maximum amount of memory available double ratio = getMemoryRatio(); @@ -75,6 +83,7 @@ this.openableCache = new ElementCache((int) (DEFAULT_OPENABLE_SIZE * ratio)); } this.childrenCache = new HashMap((int) (DEFAULT_CHILDREN_SIZE * ratio)); + resetJarTypeCache(); } /** @@ -93,6 +102,12 @@ case IJavaElement.COMPILATION_UNIT: case IJavaElement.CLASS_FILE: return this.openableCache.get(element); + case IJavaElement.TYPE: + Object result = this.jarTypeCache.get(element); + if (result != null) + return result; + else + return this.childrenCache.get(element); default: return this.childrenCache.get(element); } @@ -125,6 +140,12 @@ case IJavaElement.COMPILATION_UNIT: case IJavaElement.CLASS_FILE: return this.openableCache.peek(element); + case IJavaElement.TYPE: + Object result = this.jarTypeCache.peek(element); + if (result != null) + return result; + else + return this.childrenCache.get(element); default: return this.childrenCache.get(element); } @@ -186,6 +207,12 @@ this.childrenCache.remove(element); } } +protected void resetJarTypeCache() { + this.jarTypeCache = new LRUCache((int) (DEFAULT_OPENABLE_SIZE * getMemoryRatio())); +} +public String toString() { + return toStringFillingRation(""); //$NON-NLS-1$ +} public String toStringFillingRation(String prefix) { StringBuffer buffer = new StringBuffer(); buffer.append(prefix); @@ -201,6 +228,8 @@ buffer.append(prefix); buffer.append(this.openableCache.toStringFillingRation("Openable cache")); //$NON-NLS-1$ buffer.append('\n'); + buffer.append(this.jarTypeCache.toStringFillingRation("Jar type cache")); //$NON-NLS-1$ + buffer.append('\n'); return buffer.toString(); } } Index: model/org/eclipse/jdt/internal/core/BinaryType.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BinaryType.java,v retrieving revision 1.137 diff -u -r1.137 BinaryType.java --- model/org/eclipse/jdt/internal/core/BinaryType.java 6 Feb 2006 12:08:34 -0000 1.137 +++ model/org/eclipse/jdt/internal/core/BinaryType.java 7 Feb 2006 12:57:13 -0000 @@ -274,6 +274,12 @@ } } } +public Object getElementInfo(IProgressMonitor monitor) throws JavaModelException { + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + Object info = manager.getInfo(this); + if (info != null && info != JavaModelCache.NON_EXISTING_JAR_TYPE_INFO) return info; + return openWhenClosed(createElementInfo(), monitor); +} /* * @see IJavaElement */ 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.322 diff -u -r1.322 JavaModelManager.java --- model/org/eclipse/jdt/internal/core/JavaModelManager.java 3 Feb 2006 15:29:44 -0000 1.322 +++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 7 Feb 2006 12:57:17 -0000 @@ -817,7 +817,7 @@ /** * Infos cache. */ - public JavaModelCache cache; + private JavaModelCache cache; /* * Temporary cache of newly opened elements @@ -2464,6 +2464,13 @@ this.cache.putInfo(element, info); } } + + /* + * Remember the info for the jar binary type + */ + protected synchronized void putJarTypeInfo(IJavaElement type, Object info) { + this.cache.jarTypeCache.put(type, info); + } /** * Reads the build state for the relevant project. @@ -2654,6 +2661,13 @@ // used by tests to simulate a startup MANAGER = new JavaModelManager(); } + + /* + * Resets the cache that holds on binary type in jar files + */ + protected synchronized void resetJarTypeCache() { + this.cache.resetJarTypeCache(); + } /* * Resets the temporary cache for newly created elements to null. @@ -3930,4 +3944,8 @@ Util.resetJavaLikeExtensions(); } + + public synchronized String cacheToString(String prefix) { + return this.cache.toStringFillingRation(prefix); + } } Index: model/org/eclipse/jdt/internal/core/util/LRUCache.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/LRUCache.java,v retrieving revision 1.21 diff -u -r1.21 LRUCache.java --- model/org/eclipse/jdt/internal/core/util/LRUCache.java 23 Feb 2005 02:47:31 -0000 1.21 +++ model/org/eclipse/jdt/internal/core/util/LRUCache.java 7 Feb 2006 12:57:19 -0000 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.util; +import java.text.NumberFormat; import java.util.Enumeration; import java.util.Hashtable; @@ -160,6 +161,9 @@ } return newCache; } + public double fillingRatio() { + return (fCurrentSpace) * 100.0 / fSpaceLimit; + } /** * Flushes all entries from the cache. */ @@ -290,6 +294,20 @@ return new LRUCache(size); } /** + * Answers the value in the cache at the given key. + * If the value is not in the cache, returns null + * + * This function does not modify timestamps. + */ + public Object peek(Object key) { + + LRUCacheEntry entry = (LRUCacheEntry) fEntryTable.get(key); + if (entry == null) { + return null; + } + return entry._fValue; + } + /** * Adds an entry for the given key/value/space. */ protected void privateAdd (Object key, Object value, int space) { @@ -443,45 +461,57 @@ return 1; } } -/** - * Returns a String that represents the value of this object. This method - * is for debugging purposes only. - */ -public String toString() { - return - "LRUCache " + (fCurrentSpace * 100.0 / fSpaceLimit) + "% full\n" + //$NON-NLS-1$ //$NON-NLS-2$ - this.toStringContents(); -} -/** - * Returns a String that represents the contents of this object. This method - * is for debugging purposes only. - */ -protected String toStringContents() { - StringBuffer result = new StringBuffer(); - int length = fEntryTable.size(); - Object[] unsortedKeys = new Object[length]; - String[] unsortedToStrings = new String[length]; - Enumeration e = this.keys(); - for (int i = 0; i < length; i++) { - Object key = e.nextElement(); - unsortedKeys[i] = key; - unsortedToStrings[i] = - (key instanceof org.eclipse.jdt.internal.core.JavaElement) ? - ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() : - key.toString(); - } - ToStringSorter sorter = new ToStringSorter(); - sorter.sort(unsortedKeys, unsortedToStrings); - for (int i = 0; i < length; i++) { - String toString = sorter.sortedStrings[i]; - Object value = this.get(sorter.sortedObjects[i]); - result.append(toString); - result.append(" -> "); //$NON-NLS-1$ - result.append(value); - result.append("\n"); //$NON-NLS-1$ + /** + * Returns a String that represents the value of this object. This method + * is for debugging purposes only. + */ + public String toString() { + return + toStringFillingRation("LRUCache") + //$NON-NLS-1$ + toStringContents(); } - return result.toString(); -} + + /** + * Returns a String that represents the contents of this object. This method + * is for debugging purposes only. + */ + protected String toStringContents() { + StringBuffer result = new StringBuffer(); + int length = fEntryTable.size(); + Object[] unsortedKeys = new Object[length]; + String[] unsortedToStrings = new String[length]; + Enumeration e = this.keys(); + for (int i = 0; i < length; i++) { + Object key = e.nextElement(); + unsortedKeys[i] = key; + unsortedToStrings[i] = + (key instanceof org.eclipse.jdt.internal.core.JavaElement) ? + ((org.eclipse.jdt.internal.core.JavaElement)key).getElementName() : + key.toString(); + } + ToStringSorter sorter = new ToStringSorter(); + sorter.sort(unsortedKeys, unsortedToStrings); + for (int i = 0; i < length; i++) { + String toString = sorter.sortedStrings[i]; + Object value = this.get(sorter.sortedObjects[i]); + result.append(toString); + result.append(" -> "); //$NON-NLS-1$ + result.append(value); + result.append("\n"); //$NON-NLS-1$ + } + return result.toString(); + } + + public String toStringFillingRation(String cacheName) { + StringBuffer buffer = new StringBuffer(cacheName); + buffer.append('['); + buffer.append(getSpaceLimit()); + buffer.append("]: "); //$NON-NLS-1$ + buffer.append(NumberFormat.getInstance().format(fillingRatio())); + buffer.append("% full"); //$NON-NLS-1$ + return buffer.toString(); + } + /** * Updates the timestamp for the given entry, ensuring that the queue is * kept in correct order. The entry must exist #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java,v retrieving revision 1.47 diff -u -r1.47 TypeHierarchyTests.java --- src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java 26 Sep 2005 19:34:11 -0000 1.47 +++ src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java 7 Feb 2006 12:57:22 -0000 @@ -374,7 +374,7 @@ "Focus: Y [in Y.class [in p [in " + externalJar2 + " [in P]]]]\n" + "Super types:\n" + " X [in X.class [in p [in " + externalJar1 + " [in P]]]]\n" + - " Object [in Object.class [in java.lang [in "+ getExternalJCLPathString() + " [in TypeHierarchy]]]]\n" + + " Object [in Object.class [in java.lang [in "+ getExternalJCLPathString() + " [in P]]]]\n" + "Sub types:\n", focus.newTypeHierarchy(null) ); @@ -721,7 +721,16 @@ "Sub types of root classes:\n" + " X [in X.java [in [in [in P1]]]]\n" + " Z [in Z.java [in [in [in P3]]]]\n" + - " Y [in Y.java [in [in [in P2]]]]\n", + " Y [in Y.java [in [in [in P2]]]]\n" + + " Throwable [in Throwable.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " Exception [in Exception.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " RuntimeException [in RuntimeException.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " IllegalMonitorStateException [in IllegalMonitorStateException.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " InterruptedException [in InterruptedException.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " CloneNotSupportedException [in CloneNotSupportedException.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " Error [in Error.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " String [in String.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " Class [in Class.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n", hierarchy); } finally { deleteProjects(new String[] {"P1", "P2", "P3"}); @@ -753,7 +762,7 @@ assertHierarchyEquals( "Focus: Member [in X [in X.java [in [in [in P1]]]]]\n" + "Super types:\n" + - " Object [in Object.class [in java.lang [in "+ getExternalJCLPathString() + " [in P1]]]]\n" + + " Object [in Object.class [in java.lang [in "+ getExternalJCLPathString() + " [in P2]]]]\n" + "Sub types:\n" + " Y [in Y.java [in [in [in P2]]]]\n", hierarchy);