1 11 package org.eclipse.jdt.internal.corext.util; 12 13 import java.util.ArrayList ; 14 import java.util.Iterator ; 15 import java.util.Map ; 16 17 import org.eclipse.core.runtime.IProgressMonitor; 18 19 import org.eclipse.jdt.core.IType; 20 import org.eclipse.jdt.core.ITypeHierarchy; 21 import org.eclipse.jdt.core.ITypeHierarchyChangedListener; 22 import org.eclipse.jdt.core.JavaModelException; 23 24 public class SuperTypeHierarchyCache { 25 26 private static class HierarchyCacheEntry implements ITypeHierarchyChangedListener { 27 28 private ITypeHierarchy fTypeHierarchy; 29 private long fLastAccess; 30 31 public HierarchyCacheEntry(ITypeHierarchy hierarchy) { 32 fTypeHierarchy= hierarchy; 33 fTypeHierarchy.addTypeHierarchyChangedListener(this); 34 markAsAccessed(); 35 } 36 37 public void typeHierarchyChanged(ITypeHierarchy typeHierarchy) { 38 removeHierarchyEntryFromCache(this); 39 } 40 41 public ITypeHierarchy getTypeHierarchy() { 42 return fTypeHierarchy; 43 } 44 45 public void markAsAccessed() { 46 fLastAccess= System.currentTimeMillis(); 47 } 48 49 public long getLastAccess() { 50 return fLastAccess; 51 } 52 53 public void dispose() { 54 fTypeHierarchy.removeTypeHierarchyChangedListener(this); 55 fTypeHierarchy= null; 56 } 57 58 61 public String toString() { 62 return "Super hierarchy of: " + fTypeHierarchy.getType().getElementName(); } 64 65 } 66 67 68 private static final int CACHE_SIZE= 8; 69 70 private static ArrayList fgHierarchyCache= new ArrayList (CACHE_SIZE); 71 private static Map fgMethodOverrideTesterCache= new LRUMap(CACHE_SIZE); 72 73 private static int fgCacheHits= 0; 74 private static int fgCacheMisses= 0; 75 76 79 public static ITypeHierarchy getTypeHierarchy(IType type) throws JavaModelException { 80 return getTypeHierarchy(type, null); 81 } 82 83 public static MethodOverrideTester getMethodOverrideTester(IType type) throws JavaModelException { 84 MethodOverrideTester test= null; 85 synchronized (fgMethodOverrideTesterCache) { 86 test= (MethodOverrideTester) fgMethodOverrideTesterCache.get(type); 87 } 88 if (test == null) { 89 ITypeHierarchy hierarchy= getTypeHierarchy(type); synchronized (fgMethodOverrideTesterCache) { 91 test= (MethodOverrideTester) fgMethodOverrideTesterCache.get(type); if (test == null) { 93 test= new MethodOverrideTester(type, hierarchy); 94 fgMethodOverrideTesterCache.put(type, test); 95 } 96 } 97 } 98 return test; 99 } 100 101 private static void removeMethodOverrideTester(ITypeHierarchy hierarchy) { 102 synchronized (fgMethodOverrideTesterCache) { 103 for (Iterator iter= fgMethodOverrideTesterCache.values().iterator(); iter.hasNext();) { 104 MethodOverrideTester curr= (MethodOverrideTester) iter.next(); 105 if (curr.getTypeHierarchy().equals(hierarchy)) { 106 iter.remove(); 107 } 108 } 109 } 110 } 111 112 113 116 public static ITypeHierarchy getTypeHierarchy(IType type, IProgressMonitor progressMonitor) throws JavaModelException { 117 ITypeHierarchy hierarchy= findTypeHierarchyInCache(type); 118 if (hierarchy == null) { 119 fgCacheMisses++; 120 hierarchy= type.newSupertypeHierarchy(progressMonitor); 121 addTypeHierarchyToCache(hierarchy); 122 } else { 123 fgCacheHits++; 124 } 125 return hierarchy; 126 } 127 128 private static void addTypeHierarchyToCache(ITypeHierarchy hierarchy) { 129 synchronized (fgHierarchyCache) { 130 int nEntries= fgHierarchyCache.size(); 131 if (nEntries >= CACHE_SIZE) { 132 HierarchyCacheEntry oldest= null; 134 ArrayList obsoleteHierarchies= new ArrayList (CACHE_SIZE); 135 for (int i= 0; i < nEntries; i++) { 136 HierarchyCacheEntry entry= (HierarchyCacheEntry) fgHierarchyCache.get(i); 137 ITypeHierarchy curr= entry.getTypeHierarchy(); 138 if (!curr.exists() || hierarchy.contains(curr.getType())) { 139 obsoleteHierarchies.add(entry); 140 } else { 141 if (oldest == null || entry.getLastAccess() < oldest.getLastAccess()) { 142 oldest= entry; 143 } 144 } 145 } 146 if (!obsoleteHierarchies.isEmpty()) { 147 for (int i= 0; i < obsoleteHierarchies.size(); i++) { 148 removeHierarchyEntryFromCache((HierarchyCacheEntry) obsoleteHierarchies.get(i)); 149 } 150 } else if (oldest != null) { 151 removeHierarchyEntryFromCache(oldest); 152 } 153 } 154 HierarchyCacheEntry newEntry= new HierarchyCacheEntry(hierarchy); 155 fgHierarchyCache.add(newEntry); 156 } 157 } 158 159 160 165 public static boolean hasInCache(IType type) { 166 return findTypeHierarchyInCache(type) != null; 167 } 168 169 170 private static ITypeHierarchy findTypeHierarchyInCache(IType type) { 171 synchronized (fgHierarchyCache) { 172 for (int i= fgHierarchyCache.size() - 1; i>= 0; i--) { 173 HierarchyCacheEntry curr= (HierarchyCacheEntry) fgHierarchyCache.get(i); 174 ITypeHierarchy hierarchy= curr.getTypeHierarchy(); 175 if (!hierarchy.exists()) { 176 removeHierarchyEntryFromCache(curr); 177 } else { 178 if (hierarchy.contains(type)) { 179 curr.markAsAccessed(); 180 return hierarchy; 181 } 182 } 183 } 184 } 185 return null; 186 } 187 188 private static void removeHierarchyEntryFromCache(HierarchyCacheEntry entry) { 189 synchronized (fgHierarchyCache) { 190 removeMethodOverrideTester(entry.getTypeHierarchy()); 191 entry.dispose(); 192 fgHierarchyCache.remove(entry); 193 } 194 } 195 196 197 201 public static int getCacheHits() { 202 return fgCacheHits; 203 } 204 205 209 public static int getCacheMisses() { 210 return fgCacheMisses; 211 } 212 } 213 | Popular Tags |