diff options
Diffstat (limited to 'java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java')
-rw-r--r-- | java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java new file mode 100644 index 000000000000..067cc743679e --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/bytecodeAnalysis/BytecodeAnalysisConverterImpl.java @@ -0,0 +1,206 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.codeInspection.bytecodeAnalysis; + +import com.intellij.ide.util.PropertiesComponent; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.util.ThrowableComputable; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.util.io.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.*; +import java.io.DataOutputStream; +import java.util.Arrays; + +import static com.intellij.codeInspection.bytecodeAnalysis.ProjectBytecodeAnalysis.LOG; + +/** + * @author lambdamix + */ +public class BytecodeAnalysisConverterImpl extends BytecodeAnalysisConverter { + private static final int LOGIC_VERSION = 1; + private static final String ENUMERATORS_VERSION_KEY = "BytecodeAnalysisConverter.Enumerators"; + + private File myVersionFile; + private PersistentStringEnumerator myNamesEnumerator; + private PersistentEnumeratorDelegate<int[]> myCompoundKeyEnumerator; + private int version; + + @Override + public void initComponent() { + + // suffix as an indicator of version + final File keysDir = new File(PathManager.getIndexRoot(), "bytecodekeys"); + final File namesFile = new File(keysDir, "names" + LOGIC_VERSION); + final File compoundKeysFile = new File(keysDir, "compound" + LOGIC_VERSION); + myVersionFile = new File(keysDir, "version" + LOGIC_VERSION); + + version = PropertiesComponent.getInstance().getOrInitInt(ENUMERATORS_VERSION_KEY, 0); + if (ApplicationManager.getApplication().isUnitTestMode()) { + version = _readVersion(); + } + + if (!namesFile.exists() || !compoundKeysFile.exists() || !myVersionFile.exists()) { + LOG.info("No enumerators detected, re-initialization of enumerators."); + IOUtil.deleteAllFilesStartingWith(keysDir); + version++; + } + + try { + IOUtil.openCleanOrResetBroken(new ThrowableComputable<Void, IOException>() { + @Override + public Void compute() throws IOException { + myNamesEnumerator = new PersistentStringEnumerator(namesFile, true); + myCompoundKeyEnumerator = new IntArrayPersistentEnumerator(compoundKeysFile, new IntArrayKeyDescriptor()); + return null; + } + }, new Runnable() { + @Override + public void run() { + LOG.info("Error during initialization of enumerators in bytecode analysis. Re-initializing."); + IOUtil.deleteAllFilesStartingWith(keysDir); + version++; + } + }); + } + catch (IOException e) { + LOG.error("Re-initialization of enumerators in bytecode analysis failed.", e); + } + PropertiesComponent.getInstance().setValue(ENUMERATORS_VERSION_KEY, String.valueOf(version)); + _saveVersion(); + } + + @Override + public void disposeComponent() { + try { + myNamesEnumerator.close(); + myCompoundKeyEnumerator.close(); + } + catch (IOException e) { + LOG.debug(e); + } + } + + public int _readVersion() { + try { + final DataInputStream is = new DataInputStream(new FileInputStream(myVersionFile)); + try { + return is.readInt(); + } + finally { + is.close(); + } + } + catch (FileNotFoundException ignored) { + } + catch (IOException ignored) { + } + return 0; + } + + private void _saveVersion() { + try { + FileUtil.createIfDoesntExist(myVersionFile); + final DataOutputStream os = new DataOutputStream(new FileOutputStream(myVersionFile)); + try { + os.writeInt(version); + } + finally { + os.close(); + } + } + catch (IOException ignored) { + } + } + + public int getVersion() { + return version; + } + + @Override + protected int enumerateString(@NotNull String s) throws IOException { + return myNamesEnumerator.enumerate(s); + } + + @Override + protected int enumerateCompoundKey(@NotNull int[] key) throws IOException { + return myCompoundKeyEnumerator.enumerate(key); + } + + private static class IntArrayKeyDescriptor implements KeyDescriptor<int[]>, DifferentSerializableBytesImplyNonEqualityPolicy { + + @Override + public void save(@NotNull DataOutput out, int[] value) throws IOException { + DataInputOutputUtil.writeINT(out, value.length); + for (int i : value) { + DataInputOutputUtil.writeINT(out, i); + } + } + + @Override + public int[] read(@NotNull DataInput in) throws IOException { + int[] value = new int[DataInputOutputUtil.readINT(in)]; + for (int i = 0; i < value.length; i++) { + value[i] = DataInputOutputUtil.readINT(in); + } + return value; + } + + @Override + public int getHashCode(int[] value) { + return Arrays.hashCode(value); + } + + @Override + public boolean isEqual(int[] val1, int[] val2) { + return Arrays.equals(val1, val2); + } + } + + private static class IntArrayPersistentEnumerator extends PersistentEnumeratorDelegate<int[]> { + private final CachingEnumerator<int[]> myCache; + + public IntArrayPersistentEnumerator(File compoundKeysFile, IntArrayKeyDescriptor descriptor) throws IOException { + super(compoundKeysFile, descriptor, 1024 * 4); + myCache = new CachingEnumerator<int[]>(new DataEnumerator<int[]>() { + @Override + public int enumerate(@Nullable int[] value) throws IOException { + return IntArrayPersistentEnumerator.super.enumerate(value); + } + + @Nullable + @Override + public int[] valueOf(int idx) throws IOException { + return IntArrayPersistentEnumerator.super.valueOf(idx); + } + }, descriptor); + } + + @Override + public int enumerate(@Nullable int[] value) throws IOException { + return myCache.enumerate(value); + } + + @Nullable + @Override + public int[] valueOf(int idx) throws IOException { + return myCache.valueOf(idx); + } + } +} |