cleanup deprecated descriptors
[fedora-idea.git] / java / compiler / impl / src / com / intellij / compiler / make / Cache.java
blob99740fa761a6cbe1add43579f66a857e6ace49d3
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.compiler.make;
18 import com.intellij.compiler.SymbolTable;
19 import com.intellij.compiler.classParsing.*;
20 import com.intellij.openapi.diagnostic.Logger;
21 import com.intellij.openapi.util.io.FileUtil;
22 import com.intellij.util.ArrayUtil;
23 import com.intellij.util.cls.ClsFormatException;
24 import com.intellij.util.io.DataExternalizer;
25 import com.intellij.util.io.EnumeratorIntegerDescriptor;
26 import com.intellij.util.io.PersistentHashMap;
27 import org.jetbrains.annotations.NonNls;
28 import org.jetbrains.annotations.Nullable;
30 import java.io.DataInput;
31 import java.io.DataOutput;
32 import java.io.File;
33 import java.io.IOException;
34 import java.util.*;
36 /**
37 * @author Eugene Zhuravlev
38 * Date: Aug 8, 2003
39 * Time: 7:03:56 PM
41 public class Cache {
42 private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.make.Cache");
43 public static final int UNKNOWN = -1;
45 private final PersistentHashMap<Integer, ClassInfo> myQNameToClassInfoMap;
47 private final BackwardDependenciesStorage myDependencies;
48 private final CompilerDependencyStorage<Integer> myQNameToReferencedClassesMap;
49 private final CompilerDependencyStorage<Integer> myQNameToSubclassesMap;
50 private final PersistentHashMap<Integer, Boolean> myRemoteQNames;
51 private final String myStorePath;
53 public Cache(@NonNls final String storePath, final int cacheSize) throws IOException {
54 myStorePath = storePath;
55 new File(storePath).mkdirs();
56 myQNameToClassInfoMap = new CachedPersistentHashMap<Integer, ClassInfo>(getOrCreateFile("classes"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<ClassInfo>() {
57 public void save(DataOutput out, ClassInfo value) throws IOException {
58 value.save(out);
60 public ClassInfo read(DataInput in) throws IOException {
61 return new ClassInfo(in);
63 }, cacheSize * 2) {
64 protected boolean isValueDirty(ClassInfo classInfo) {
65 return classInfo.isDirty();
69 myDependencies = new BackwardDependenciesStorage(getOrCreateFile("bdeps"), cacheSize);
70 myQNameToReferencedClassesMap = new CompilerDependencyStorage<Integer>(getOrCreateFile("fdeps"), EnumeratorIntegerDescriptor.INSTANCE, cacheSize);
71 myQNameToSubclassesMap = new CompilerDependencyStorage<Integer>(getOrCreateFile("subclasses"), EnumeratorIntegerDescriptor.INSTANCE, cacheSize);
73 myRemoteQNames = new PersistentHashMap<Integer, Boolean>(getOrCreateFile("remote"), EnumeratorIntegerDescriptor.INSTANCE, new DataExternalizer<Boolean>() {
74 public void save(DataOutput out, Boolean value) throws IOException {
75 out.writeBoolean(value.booleanValue());
78 public Boolean read(DataInput in) throws IOException {
79 return in.readBoolean();
81 }, cacheSize);
84 private File getOrCreateFile(final String fileName) throws IOException {
85 final File file = new File(myStorePath, fileName);
86 FileUtil.createIfDoesntExist(file);
87 return file;
90 public void dispose() throws CacheCorruptedException {
91 CacheCorruptedException ex = null;
92 try {
93 myQNameToClassInfoMap.close();
95 catch (IOException e) {
96 LOG.info(e);
97 ex = new CacheCorruptedException(e);
99 try {
100 myRemoteQNames.close();
102 catch (IOException e) {
103 LOG.info(e);
104 if (ex != null) {
105 ex = new CacheCorruptedException(e);
109 myQNameToReferencedClassesMap.dispose();
110 myDependencies.dispose();
111 myQNameToSubclassesMap.dispose();
113 if (ex != null) {
114 throw ex;
119 public int[] getAllClassNames() throws CacheCorruptedException {
120 try {
121 final Collection<Integer> allKeys = myQNameToClassInfoMap.getAllKeysWithExistingMapping();
122 final int[] array = ArrayUtil.newIntArray(allKeys.size());
123 int idx = 0;
124 for (Integer id : allKeys) {
125 array[idx++] = id.intValue();
127 return array;
129 catch (IOException e) {
130 throw new CacheCorruptedException(e);
134 public int importClassInfo(ClassFileReader reader, SymbolTable symbolTable) throws ClsFormatException, CacheCorruptedException {
135 try {
136 final ClassInfo classInfo = new ClassInfo(reader, symbolTable);
137 myQNameToClassInfoMap.put(classInfo.getQualifiedName(), classInfo);
138 return classInfo.getQualifiedName();
140 catch (IOException e) {
141 throw new CacheCorruptedException(e);
145 public void importClassInfo(Cache fromCache, final int qName) throws CacheCorruptedException {
146 try {
147 final ClassInfo classInfo = fromCache.myQNameToClassInfoMap.get(qName);
148 if (classInfo != null) {
149 final ClassInfo clone = classInfo.clone();
150 clone.clearReferences();
151 myQNameToClassInfoMap.put(qName, clone);
154 catch (Throwable e) {
155 throw new CacheCorruptedException(e);
159 public AnnotationConstantValue[] getRuntimeVisibleAnnotations(int classId) throws CacheCorruptedException {
160 try {
161 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
162 return classInfo != null? classInfo.getRuntimeVisibleAnnotations() : AnnotationConstantValue.EMPTY_ARRAY;
164 catch (Throwable e) {
165 throw new CacheCorruptedException(e);
169 public AnnotationConstantValue[] getRuntimeInvisibleAnnotations(int classId) throws CacheCorruptedException {
170 try {
171 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
172 return classInfo != null? classInfo.getRuntimeInvisibleAnnotations() : AnnotationConstantValue.EMPTY_ARRAY;
174 catch (Throwable e) {
175 throw new CacheCorruptedException(e);
179 public int[] getSubclasses(int classId) throws CacheCorruptedException {
180 try {
181 return myQNameToSubclassesMap.getValues(classId);
183 catch (Throwable e) {
184 throw new CacheCorruptedException(e);
188 public void addSubclass(int classId, int subclassQName) throws CacheCorruptedException {
189 try {
190 myQNameToSubclassesMap.addValue(classId, subclassQName);
192 catch (Throwable e) {
193 throw new CacheCorruptedException(e);
197 public void removeSubclass(int classId, int subclassQName) throws CacheCorruptedException {
198 try {
199 myQNameToSubclassesMap.removeValue(classId, subclassQName);
201 catch (Throwable e) {
202 throw new CacheCorruptedException(e);
206 public int[] getReferencedClasses(int classId) throws CacheCorruptedException {
207 try {
208 return myQNameToReferencedClassesMap.getValues(classId);
210 catch (Throwable e) {
211 throw new CacheCorruptedException(e);
215 public void clearReferencedClasses(int qName) throws CacheCorruptedException {
216 try {
217 myQNameToReferencedClassesMap.remove(qName);
219 catch (Throwable e) {
220 throw new CacheCorruptedException(e);
224 public Collection<ReferenceInfo> getReferences(int classId) throws CacheCorruptedException {
225 try {
226 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
227 return classInfo != null? Arrays.asList(classInfo.getReferences()) : Collections.<ReferenceInfo>emptyList();
229 catch (Throwable e) {
230 throw new CacheCorruptedException(e);
234 public String getSourceFileName(int classId) throws CacheCorruptedException {
235 try {
236 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
237 return classInfo != null? classInfo.getSourceFileName() : "";
239 catch (Throwable e) {
240 throw new CacheCorruptedException(e);
244 public boolean isRemote(int classId) throws CacheCorruptedException {
245 try {
246 return myRemoteQNames.containsMapping(classId);
248 catch (Throwable e) {
249 throw new CacheCorruptedException(e);
253 public void setRemote(int classId, boolean remote) throws CacheCorruptedException {
254 try {
255 if (remote) {
256 myRemoteQNames.put(classId, Boolean.TRUE);
258 else {
259 myRemoteQNames.remove(classId);
262 catch (Throwable e) {
263 throw new CacheCorruptedException(e);
267 public int getSuperQualifiedName(int classId) throws CacheCorruptedException {
268 try {
269 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
270 return classInfo != null? classInfo.getSuperQualifiedName() : UNKNOWN;
272 catch (Throwable e) {
273 throw new CacheCorruptedException(e);
277 public String getPath(int classId) throws CacheCorruptedException {
278 try {
279 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
280 return classInfo != null? classInfo.getPath() : "";
282 catch (Throwable e) {
283 throw new CacheCorruptedException(e);
287 public void setPath(int classId, String path) throws CacheCorruptedException {
288 try {
289 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
290 if (classInfo != null) {
291 classInfo.setPath(path);
294 catch (Throwable e) {
295 throw new CacheCorruptedException(e);
299 public int getGenericSignature(int classId) throws CacheCorruptedException {
300 try {
301 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
302 return classInfo != null? classInfo.getGenericSignature() : UNKNOWN;
304 catch (Throwable e) {
305 throw new CacheCorruptedException(e);
309 public boolean containsClass(int qName) throws CacheCorruptedException {
310 try {
311 return myQNameToClassInfoMap.containsMapping(qName);
313 catch (IOException e) {
314 throw new CacheCorruptedException(e);
318 public int[] getSuperInterfaces(int classId) throws CacheCorruptedException {
319 try {
320 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
321 return classInfo != null? classInfo.getSuperInterfaces() : ArrayUtil.EMPTY_INT_ARRAY;
323 catch (Throwable e) {
324 throw new CacheCorruptedException(e);
328 public int getFlags(int classId) throws CacheCorruptedException {
329 try {
330 final ClassInfo classInfo = myQNameToClassInfoMap.get(classId);
331 return classInfo != null? classInfo.getFlags() : UNKNOWN;
333 catch (Throwable e) {
334 throw new CacheCorruptedException(e);
338 public FieldInfo[] getFields(int qName) throws CacheCorruptedException{
339 try {
340 final ClassInfo classInfo = myQNameToClassInfoMap.get(qName);
341 return classInfo != null? classInfo.getFields() : FieldInfo.EMPTY_ARRAY;
343 catch (Throwable e) {
344 throw new CacheCorruptedException(e);
348 @Nullable
349 public FieldInfo findField(final int classDeclarationId, final int name, final int descriptor) throws CacheCorruptedException{
350 try {
351 for (FieldInfo fieldInfo : getFields(classDeclarationId)) {
352 if (fieldInfo.getName() == name && fieldInfo.getDescriptor() == descriptor) {
353 return fieldInfo;
356 return null;
358 catch (Throwable e) {
359 throw new CacheCorruptedException(e);
363 @Nullable
364 public FieldInfo findFieldByName(final int classDeclarationId, final int name) throws CacheCorruptedException{
365 try {
366 for (FieldInfo fieldInfo : getFields(classDeclarationId)) {
367 if (fieldInfo.getName() == name) {
368 return fieldInfo;
371 return null;
373 catch (Throwable e) {
374 throw new CacheCorruptedException(e);
378 public MethodInfo[] getMethods(int classQName) throws CacheCorruptedException{
379 try {
380 final ClassInfo classInfo = myQNameToClassInfoMap.get(classQName);
381 return classInfo != null? classInfo.getMethods() : MethodInfo.EMPTY_ARRAY;
383 catch (Throwable e) {
384 throw new CacheCorruptedException(e);
388 @Nullable
389 public MethodInfo findMethod(final int classQName, final int name, final int descriptor) throws CacheCorruptedException{
390 try {
391 for (MethodInfo methodInfo : getMethods(classQName)) {
392 if (methodInfo.getName() == name && methodInfo.getDescriptor() == descriptor) {
393 return methodInfo;
396 return null;
398 catch (Throwable e) {
399 throw new CacheCorruptedException(e);
403 public List<MethodInfo> findMethodsByName(final int classDeclarationId, final int name) throws CacheCorruptedException{
404 try {
405 final List<MethodInfo> methods = new ArrayList<MethodInfo>();
406 for (MethodInfo methodInfo : getMethods(classDeclarationId)) {
407 if (methodInfo.getName() == name) {
408 methods.add(methodInfo);
411 return methods;
413 catch (Throwable e) {
414 throw new CacheCorruptedException(e);
418 @Nullable
419 public MethodInfo findMethodsBySignature(final int classDeclarationId, final String signature, SymbolTable symbolTable) throws CacheCorruptedException{
420 try {
421 for (MethodInfo methodInfo : getMethods(classDeclarationId)) {
422 if (signature.equals(CacheUtils.getMethodSignature(symbolTable.getSymbol(methodInfo.getName()), symbolTable.getSymbol(methodInfo.getDescriptor())))) {
423 return methodInfo;
426 return null;
428 catch (Throwable e) {
429 throw new CacheCorruptedException(e);
433 public void addClassReferencer(int qName, int referencerQName) throws CacheCorruptedException {
434 try {
435 if (qName == referencerQName) {
436 return; // do not log self-dependencies
438 if (myQNameToClassInfoMap.containsMapping(qName)) {
439 myDependencies.addClassReferencer(qName, referencerQName);
440 myQNameToReferencedClassesMap.addValue(referencerQName, qName);
443 catch (Throwable e) {
444 throw new CacheCorruptedException(e);
448 public void removeClassReferencer(int qName, int referencerQName) throws CacheCorruptedException {
449 try {
450 myDependencies.removeReferencer(qName, referencerQName);
452 catch (Throwable e) {
453 throw new CacheCorruptedException(e);
457 public void addFieldReferencer(int qName, int fieldName, int referencerQName) throws CacheCorruptedException {
458 try {
459 if (qName != referencerQName && myQNameToClassInfoMap.containsMapping(qName)) {
460 myDependencies.addFieldReferencer(qName, referencerQName, fieldName);
461 myQNameToReferencedClassesMap.addValue(referencerQName, qName);
464 catch (Throwable e) {
465 throw new CacheCorruptedException(e);
469 public void addMethodReferencer(int qName, int methodName, int methodDescriptor, int referencerQName) throws CacheCorruptedException {
470 try {
471 if (qName != referencerQName && myQNameToClassInfoMap.containsMapping(qName)) {
472 myDependencies.addMethodReferencer(qName, referencerQName, methodName, methodDescriptor);
473 myQNameToReferencedClassesMap.addValue(referencerQName, qName);
476 catch (Throwable e) {
477 throw new CacheCorruptedException(e);
481 /** @NotNull */
482 public Dependency[] getBackDependencies(final int classQName) throws CacheCorruptedException{
483 return myDependencies.getDependencies(classQName);
486 public void wipe() {
487 myDependencies.dispose();
488 myQNameToReferencedClassesMap.dispose();
489 myQNameToSubclassesMap.dispose();
490 try {
491 myQNameToClassInfoMap.close();
493 catch (IOException e) {
494 LOG.info(e);
496 try {
497 myRemoteQNames.close();
499 catch (IOException e) {
500 LOG.info(e);
502 final File[] files = new File(myStorePath).listFiles();
503 if (files != null) {
504 for (File file : files) {
505 if (!file.isDirectory()) {
506 FileUtil.delete(file);
512 public void removeClass(final int qName) throws CacheCorruptedException {
513 try {
514 final ClassInfo classInfo = myQNameToClassInfoMap.get(qName);
515 if (classInfo == null) {
516 return;
518 myDependencies.remove(qName);
519 myQNameToClassInfoMap.remove(qName);
520 myQNameToReferencedClassesMap.remove(qName);
521 myQNameToSubclassesMap.remove(qName);
522 myRemoteQNames.remove(qName);
524 catch (Throwable e) {
525 throw new CacheCorruptedException(e);