\n" +
+ " \n" +
+ "");
}
public void testReloadProfileWithUnknownScopes() throws Exception {
- final Element element = JDOMUtil.loadDocument("\n" +
+ final Element element = JdomKt.loadElement("\n" +
"
\n" +
" \n" +
" \n" +
@@ -199,32 +196,28 @@ public class InspectionProfileTest extends LightIdeaTestCase {
" \n" +
" \n" +
" \n" +
- "").getRootElement();
+ "");
final InspectionProfileImpl profile = createProfile();
profile.readExternal(element);
final ModifiableModel model = profile.getModifiableModel();
model.commit();
- final Element copy = new Element("inspections");
- profile.writeExternal(copy);
- assertElementsEqual(element, copy);
+ assertElementsEqual(element, profile.writeExternal());
}
public void testMergeUnusedDeclarationAndUnusedSymbol() throws Exception {
//no specific settings
- final Element element = JDOMUtil.loadDocument("\n" +
+ final Element element = JdomKt.loadElement("\n" +
"
\n" +
- "").getRootElement();
+ "");
InspectionProfileImpl profile = createProfile(new InspectionProfileImpl("foo"));
profile.readExternal(element);
ModifiableModel model = profile.getModifiableModel();
model.commit();
- final Element copy = new Element("inspections");
- profile.writeExternal(copy);
- assertElementsEqual(element, copy);
+ assertElementsEqual(element, profile.writeExternal());
//settings to merge
- final Element unusedProfile = JDOMUtil.loadDocument("\n" +
+ final Element unusedProfile = JdomKt.loadElement("\n" +
"
\n" +
" \n" +
"
\n" +
@@ -240,7 +233,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
"
\n" +
"
\n" +
" \n" +
- "").getRootElement();
+ "");
profile.readExternal(unusedProfile);
model = profile.getModifiableModel();
model.commit();
@@ -292,8 +285,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
"";
assertEquals(mergedText, serialize(profile));
- Element toImportElement = new Element("profile");
- profile.writeExternal(toImportElement);
+ Element toImportElement = profile.writeExternal();
final InspectionProfileImpl importedProfile =
InspectionToolsConfigurable.importInspectionProfile(toImportElement, InspectionProfileManager.getInstance(), getProject(), null);
@@ -303,13 +295,9 @@ public class InspectionProfileTest extends LightIdeaTestCase {
profile.readExternal(mergedElement);
model = profile.getModifiableModel();
model.commit();
- Element copyMerged = new Element("profile");
- profile.writeExternal(copyMerged);
- assertElementsEqual(mergedElement, copyMerged);
+ assertElementsEqual(mergedElement, profile.writeExternal());
- Element imported = new Element("profile");
- importedProfile.writeExternal(imported);
- assertElementsEqual(mergedElement, imported);
+ assertElementsEqual(mergedElement, importedProfile.writeExternal());
}
public void testDisabledUnusedDeclarationWithoutChanges() throws Exception {
@@ -419,8 +407,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
"",
serialize(profile));
- Element element = new Element("element");
- profile.writeExternal(element);
+ Element element = profile.writeExternal();
list.add(createTool("bar", true));
list.add(createTool("disabled", false));
@@ -447,9 +434,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
}
private static String serialize(InspectionProfileImpl profile) throws WriteExternalException {
- Element element = new Element("profile");
- profile.writeExternal(element);
- return JDOMUtil.writeElement(element);
+ return JDOMUtil.writeElement(profile.writeExternal());
}
private static InspectionProfileImpl createProfile(@NotNull InspectionToolRegistrar registrar) {
@@ -508,7 +493,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
profile.enableTool(id, getProject());
}
assertEquals(0, countInitializedTools(profile));
- profile.writeExternal(new Element("profile"));
+ profile.writeExternal();
List initializedTools = getInitializedTools(profile);
if (initializedTools.size() > 0) {
for (InspectionToolWrapper initializedTool : initializedTools) {
@@ -543,9 +528,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
"";
foo.readExternal(JDOMUtil.loadDocument(test).getRootElement());
foo.initInspectionTools(getProject());
- Element serialized = new Element("profile");
- foo.writeExternal(serialized);
- assertEquals(test, JDOMUtil.writeElement(serialized));
+ assertEquals(test, JDOMUtil.writeElement(foo.writeExternal()));
}
public static int countInitializedTools(Profile foo) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionSchemeTest.kt b/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionSchemeTest.kt
new file mode 100644
index 000000000000..7e97e48a8db2
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/ex/InspectionSchemeTest.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2000-2016 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.ex
+
+import com.intellij.configurationStore.SchemeManagerFactoryBase
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.util.Computable
+import com.intellij.testFramework.ProjectRule
+import com.intellij.testFramework.TemporaryDirectory
+import com.intellij.util.readText
+import com.intellij.util.write
+import org.assertj.core.api.Assertions.assertThat
+import org.junit.ClassRule
+import org.junit.Rule
+import org.junit.Test
+
+internal class InspectionSchemeTest {
+ companion object {
+ @JvmField
+ @ClassRule val projectRule = ProjectRule()
+ }
+
+ private val tempDirManager = TemporaryDirectory()
+ @Rule fun getTemporaryFolder() = tempDirManager
+
+ @Test fun loadSchemes() {
+ val schemeDir = tempDirManager.newPath()
+ val schemeFile = schemeDir.resolve("inspection/Bar.xml")
+ val schemeData = """
+
+
+
+ """".trimIndent()
+ schemeFile.write(schemeData)
+ val schemeManagerFactory = SchemeManagerFactoryBase.TestSchemeManagerFactory(schemeDir)
+ val profileManager = InspectionProfileManagerImpl(InspectionToolRegistrar.getInstance(), schemeManagerFactory, ApplicationManager.getApplication().messageBus)
+ profileManager.forceInitProfiles(true)
+ profileManager.initProfiles()
+
+ assertThat(profileManager.profiles).hasSize(1)
+ val scheme = profileManager.profiles.first() as InspectionProfileImpl
+ assertThat(scheme.name).isEqualTo("Bar")
+
+ InspectionProfileImpl.initAndDo(Computable { scheme.initInspectionTools(null) })
+
+ schemeManagerFactory.save()
+
+ assertThat(schemeFile.readText()).isEqualTo(schemeData)
+ profileManager.profiles
+ }
+}
diff --git a/platform/analysis-api/src/com/intellij/profile/DefaultProjectProfileManager.java b/platform/analysis-api/src/com/intellij/profile/DefaultProjectProfileManager.java
index 275fea67cc81..692e7c852a35 100644
--- a/platform/analysis-api/src/com/intellij/profile/DefaultProjectProfileManager.java
+++ b/platform/analysis-api/src/com/intellij/profile/DefaultProjectProfileManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -60,7 +60,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
private final ApplicationProfileManager myApplicationProfileManager;
- private final Map myProfiles = new THashMap();
+ private final Map myProfiles = new THashMap<>();
protected final DependencyValidationManager myHolder;
private final List myProfilesListener = ContainerUtil.createLockFreeCopyOnWriteList();
@NonNls private static final String PROJECT_DEFAULT_PROFILE_NAME = "Project Default";
@@ -101,8 +101,7 @@ public abstract class DefaultProjectProfileManager extends ProjectProfileManager
for (String profile : sortedProfiles) {
final Profile projectProfile = myProfiles.get(profile);
if (projectProfile != null) {
- Element profileElement = new Element(PROFILE);
- projectProfile.writeExternal(profileElement);
+ Element profileElement = projectProfile.writeExternal();
boolean hasSmthToSave = sortedProfiles.length > 1 || isCustomProfileUsed();
if (!hasSmthToSave) {
for (Element child : profileElement.getChildren()) {
diff --git a/platform/analysis-api/src/com/intellij/profile/Profile.java b/platform/analysis-api/src/com/intellij/profile/Profile.java
index e9945762ebc0..0c83cb11bf78 100644
--- a/platform/analysis-api/src/com/intellij/profile/Profile.java
+++ b/platform/analysis-api/src/com/intellij/profile/Profile.java
@@ -51,5 +51,12 @@ public interface Profile extends Comparable, Scheme {
void readExternal(Element element);
- void writeExternal(Element element);
+ default void writeExternal(Element element) {
+ Element result = writeExternal();
+ element.getAttributes().addAll(result.getAttributes());
+ element.addContent(result.getContent());
+ }
+
+ @NotNull
+ Element writeExternal();
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
index de1c83fedfa7..246b73624b16 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
@@ -262,6 +262,17 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
}
}
+ @NotNull
+ @Override
+ public Element writeExternal() {
+ if (myDataHolder == null) {
+ return super.writeExternal();
+ }
+ else {
+ return myDataHolder.read();
+ }
+ }
+
@NotNull
public Set getUsedSeverities() {
LOG.assertTrue(myInitialized);
@@ -565,7 +576,12 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
for (InspectionToolWrapper toolWrapper : tools) {
addTool(project, toolWrapper, dependencies);
}
- final GraphGenerator graphGenerator = GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph() {
+
+ if (dataHolder != null) {
+ dataHolder.updateDigest();
+ }
+
+ DFSTBuilder builder = new DFSTBuilder<>(GraphGenerator.create(CachingSemiGraph.create(new GraphGenerator.SemiGraph() {
@Override
public Collection getNodes() {
return dependencies.keySet();
@@ -575,9 +591,7 @@ public class InspectionProfileImpl extends ProfileEx implements ModifiableModel,
public Iterator getIn(String n) {
return dependencies.get(n).iterator();
}
- }));
-
- DFSTBuilder builder = new DFSTBuilder<>(graphGenerator);
+ })));
if (builder.isAcyclic()) {
final List scopes = builder.getSortedNodes();
myScopesOrder = ArrayUtil.toStringArray(scopes);
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java
index 324b720ef631..10e6918131c7 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionToolRegistrar.java
@@ -61,11 +61,6 @@ public class InspectionToolRegistrar {
if (!isInternal && ep.isInternal) continue;
factories.add(() -> new GlobalInspectionToolWrapper(ep));
}
- for (InspectionToolsFactory factory : Extensions.getExtensions(InspectionToolsFactory.EXTENSION_POINT_NAME)) {
- for (final InspectionProfileEntry profileEntry : factory.createTools()) {
- factories.add(() -> wrapTool(profileEntry));
- }
- }
myInspectionToolFactories.addAll(factories);
}
}
diff --git a/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java b/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java
index 388a3c8eac12..684989658088 100644
--- a/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java
+++ b/platform/analysis-impl/src/com/intellij/profile/ProfileEx.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2015 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -22,6 +22,8 @@ import com.intellij.util.xmlb.annotations.Transient;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
+import static com.intellij.profile.DefaultProjectProfileManager.PROFILE;
+
/**
* User: anna
* Date: 01-Dec-2005
@@ -63,9 +65,7 @@ public abstract class ProfileEx implements Profile {
@Override
public void copyFrom(@NotNull Profile profile) {
- Element config = new Element("config");
- profile.writeExternal(config);
- readExternal(config);
+ readExternal(profile.writeExternal());
}
@Override
@@ -116,9 +116,11 @@ public abstract class ProfileEx implements Profile {
mySerializer.writeExternal(this, element, preserveCompatibility);
}
- @Override
- public void writeExternal(Element element) {
- serializeInto(element, true);
+ @NotNull
+ public Element writeExternal() {
+ Element result = new Element(PROFILE);
+ serializeInto(result, true);
+ return result;
}
public void profileChanged() {
diff --git a/platform/configuration-store-impl/src/BinaryXmlOutputter.kt b/platform/configuration-store-impl/src/BinaryXmlOutputter.kt
index 71303360a4fb..bdcbe16be468 100644
--- a/platform/configuration-store-impl/src/BinaryXmlOutputter.kt
+++ b/platform/configuration-store-impl/src/BinaryXmlOutputter.kt
@@ -10,14 +10,10 @@ private enum class TypeMarker {
ELEMENT, CDATA, TEXT, ELEMENT_END
}
-fun writeElement(element: Element, out: OutputStream) {
+fun serializeElementToBinary(element: Element, out: OutputStream) {
writeElement(element, DataOutputStream(out))
}
-fun writeElement(element: Element, out: DataOutputStream) {
- writeElement(out, element)
-}
-
fun readElement(input: InputStream) = readElement(DataInputStream(input))
fun readElement(input: DataInputStream): Element {
@@ -38,7 +34,7 @@ private fun readContent(element: Element, input: DataInputStream) {
}
}
-private fun writeElement(out: DataOutputStream, element: Element) {
+private fun writeElement(element: Element, out: DataOutputStream) {
out.writeUTF(element.name)
writeAttributes(out, element.attributes)
@@ -47,7 +43,7 @@ private fun writeElement(out: DataOutputStream, element: Element) {
for (item in content) {
if (item is Element) {
out.writeByte(TypeMarker.ELEMENT.ordinal)
- writeElement(out, item)
+ writeElement(item, out)
}
else if (item is Text) {
if (!isAllWhitespace(item)) {
diff --git a/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt b/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt
index 4fefe19c344e..9ce81c430ae9 100644
--- a/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt
+++ b/platform/configuration-store-impl/src/SchemeManagerFactoryImpl.kt
@@ -20,7 +20,6 @@ import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.ComponentManager
import com.intellij.openapi.components.RoamingType
import com.intellij.openapi.components.SettingsSavingComponent
-import com.intellij.openapi.components.impl.stores.StateStorageManager
import com.intellij.openapi.components.stateStore
import com.intellij.openapi.options.Scheme
import com.intellij.openapi.options.SchemeManager
@@ -30,6 +29,7 @@ import com.intellij.openapi.project.Project
import com.intellij.util.SmartList
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.lang.CompoundRuntimeException
+import org.jetbrains.annotations.TestOnly
import java.nio.file.Path
import java.nio.file.Paths
@@ -38,13 +38,11 @@ const val ROOT_CONFIG = "\$ROOT_CONFIG$"
sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingComponent {
private val managers = ContainerUtil.createLockFreeCopyOnWriteList>()
- abstract val componentManager: ComponentManager
+ protected open val componentManager: ComponentManager? = null
override final fun create(directoryName: String, processor: SchemeProcessor, presentableName: String?, roamingType: RoamingType): SchemeManager {
- val storageManager = (componentManager.stateStore).stateStorageManager
-
val path = checkPath(directoryName)
- val manager = SchemeManagerImpl(path, processor, (storageManager as? StateStorageManagerImpl)?.streamProvider, pathToFile(path, storageManager), roamingType, componentManager, presentableName)
+ val manager = SchemeManagerImpl(path, processor, (componentManager?.stateStore?.stateStorageManager as? StateStorageManagerImpl)?.streamProvider, pathToFile(path), roamingType, componentManager, presentableName)
@Suppress("CAST_NEVER_SUCCEEDS")
managers.add(manager as SchemeManagerImpl)
return manager
@@ -63,7 +61,7 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo
return originalPath
}
- abstract fun pathToFile(path: String, storageManager: StateStorageManager): Path
+ abstract fun pathToFile(path: String): Path
fun process(processor: (SchemeManagerImpl) -> Unit) {
for (manager in managers) {
@@ -105,13 +103,18 @@ sealed class SchemeManagerFactoryBase : SchemeManagerFactory(), SettingsSavingCo
return path
}
- override fun pathToFile(path: String, storageManager: StateStorageManager) = Paths.get(storageManager.expandMacros(ROOT_CONFIG), path)
+ override fun pathToFile(path: String) = Paths.get(ApplicationManager.getApplication().stateStore.stateStorageManager.expandMacros(ROOT_CONFIG), path)
}
@Suppress("unused")
private class ProjectSchemeManagerFactory(private val project: Project) : SchemeManagerFactoryBase() {
override val componentManager = project
- override fun pathToFile(path: String, storageManager: StateStorageManager) = Paths.get(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
+ override fun pathToFile(path: String) = Paths.get(project.basePath, if (ProjectUtil.isDirectoryBased(project)) "${Project.DIRECTORY_STORE_FOLDER}/$path" else ".$path")
+ }
+
+ @TestOnly
+ class TestSchemeManagerFactory(private val basePath: Path) : SchemeManagerFactoryBase() {
+ override fun pathToFile(path: String) = basePath.resolve(path)
}
}
\ No newline at end of file
diff --git a/platform/configuration-store-impl/src/SchemeManagerImpl.kt b/platform/configuration-store-impl/src/SchemeManagerImpl.kt
index 3bc4f7f21dd2..bb07afc00e99 100644
--- a/platform/configuration-store-impl/src/SchemeManagerImpl.kt
+++ b/platform/configuration-store-impl/src/SchemeManagerImpl.kt
@@ -30,6 +30,7 @@ import com.intellij.openapi.project.ProjectBundle
import com.intellij.openapi.util.Comparing
import com.intellij.openapi.util.Condition
import com.intellij.openapi.util.JDOMUtil
+import com.intellij.openapi.util.WriteExternalException
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtilRt
import com.intellij.openapi.vfs.*
@@ -48,7 +49,9 @@ import org.xmlpull.mxp1.MXParser
import org.xmlpull.v1.XmlPullParser
import java.io.IOException
import java.io.InputStream
+import java.io.OutputStream
import java.nio.file.Path
+import java.security.MessageDigest
import java.util.*
import java.util.function.Function
@@ -216,7 +219,7 @@ class SchemeManagerImpl(val fileSpec: String,
val fileName = PathUtilRt.getFileName(url.path)
val extension = getFileExtension(fileName, true)
val info = ExternalInfo(fileName.substring(0, fileName.length - extension.length), extension)
- info.hash = element.getTreeHash()
+ info.digest = element.digest()
info.schemeName = scheme.name
val oldInfo = schemeToInfo.put(scheme, info)
LOG.assertTrue(oldInfo == null)
@@ -338,13 +341,24 @@ class SchemeManagerImpl(val fileSpec: String,
return info != null && schemeExtension != info.fileExtension
}
- private class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
- override fun read(): Element {
- val element = loadElement(bytes.inputStream())
- if (externalInfo.hash == 0) {
- externalInfo.hash = element.getTreeHash()
- }
- return element
+ private inner class SchemeDataHolderImpl(private val bytes: ByteArray, private val externalInfo: ExternalInfo) : SchemeDataHolder {
+ override fun read() = loadElement(bytes.inputStream())
+
+ override fun updateDigest() {
+ schemeToInfo.forEachEntry({ k, v ->
+ if (v !== externalInfo) {
+ return@forEachEntry true
+ }
+
+ @Suppress("UNCHECKED_CAST")
+ try {
+ externalInfo.digest = (processor.writeScheme(k as MUTABLE_SCHEME) as Element).digest()
+ }
+ catch (e: WriteExternalException) {
+ LOG.error("Cannot update digest", e)
+ }
+ false
+ })
}
}
@@ -395,7 +409,7 @@ class SchemeManagerImpl(val fileSpec: String,
fun createInfo(schemeName: String, element: Element?): ExternalInfo {
val info = ExternalInfo(fileNameWithoutExtension, extension)
element?.let {
- info.hash = it.getTreeHash()
+ info.digest = it.digest()
}
info.schemeName = schemeName
return info
@@ -558,14 +572,14 @@ class SchemeManagerImpl(val fileSpec: String,
fileNameWithoutExtension = nameGenerator.generateUniqueName(FileUtil.sanitizeFileName(scheme.name, false))
}
- val newHash = element!!.getTreeHash()
- if (externalInfo != null && currentFileNameWithoutExtension === fileNameWithoutExtension && newHash == externalInfo.hash) {
+ val newDigest = element!!.digest()
+ if (externalInfo != null && currentFileNameWithoutExtension === fileNameWithoutExtension && externalInfo.isDigestEquals(newDigest)) {
return
}
// save only if scheme differs from bundled
val bundledScheme = readOnlyExternalizableSchemes.get(scheme.name)
- if (bundledScheme != null && schemeToInfo.get(bundledScheme)?.hash == newHash) {
+ if (bundledScheme != null && schemeToInfo.get(bundledScheme)?.isDigestEquals(newDigest) ?: false) {
externalInfo?.scheduleDelete()
return
}
@@ -639,7 +653,7 @@ class SchemeManagerImpl(val fileSpec: String,
else {
externalInfo.setFileNameWithoutExtension(fileNameWithoutExtension, schemeExtension)
}
- externalInfo.hash = newHash
+ externalInfo.digest = newDigest
externalInfo.schemeName = scheme.name
}
@@ -889,7 +903,8 @@ class SchemeManagerImpl(val fileSpec: String,
private class ExternalInfo(var fileNameWithoutExtension: String, var fileExtension: String?) {
// we keep it to detect rename
var schemeName: String? = null
- var hash = 0
+
+ var digest: ByteArray? = null
val fileName: String
get() = "$fileNameWithoutExtension$fileExtension"
@@ -899,6 +914,8 @@ class SchemeManagerImpl(val fileSpec: String,
fileExtension = extension
}
+ fun isDigestEquals(newDigest: ByteArray) = Arrays.equals(digest, newDigest)
+
override fun toString() = fileName
}
@@ -930,4 +947,25 @@ fun createDir(ioDir: Path, requestor: Any): VirtualFile {
fun getFile(fileName: String, parent: VirtualFile, requestor: Any): VirtualFile {
return parent.findChild(fileName) ?: runWriteAction { parent.createChildData(requestor, fileName) }
+}
+
+class DigestOutputStream(val digest: MessageDigest) : OutputStream() {
+ override fun write(b: Int) {
+ digest.update(b.toByte())
+ }
+
+ override fun write(b: ByteArray, off: Int, len: Int) {
+ digest.update(b, off, len)
+ }
+
+ override fun toString(): String {
+ return "[Digest Output Stream] " + digest.toString()
+ }
+}
+
+fun Element.digest(): ByteArray {
+ // sha-1 is enough, sha-256 is slower, see https://www.nayuki.io/page/native-hash-functions-for-java
+ val digest = MessageDigest.getInstance("SHA-1")
+ serializeElementToBinary(this, DigestOutputStream(digest))
+ return digest.digest()
}
\ No newline at end of file
diff --git a/platform/configuration-store-impl/src/StateMap.kt b/platform/configuration-store-impl/src/StateMap.kt
index 6d8171a0a1b7..80d1d22f7e67 100644
--- a/platform/configuration-store-impl/src/StateMap.kt
+++ b/platform/configuration-store-impl/src/StateMap.kt
@@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReferenceArray
fun archiveState(state: Element): BufferExposingByteArrayOutputStream {
val byteOut = BufferExposingByteArrayOutputStream()
SnappyOutputStream(byteOut).use {
- writeElement(state, it)
+ serializeElementToBinary(state, it)
}
return byteOut
}
diff --git a/platform/configuration-store-impl/testSrc/BinaryXmlOutputterTest.kt b/platform/configuration-store-impl/testSrc/BinaryXmlOutputterTest.kt
index 3e178eacfaab..d15acabe782d 100644
--- a/platform/configuration-store-impl/testSrc/BinaryXmlOutputterTest.kt
+++ b/platform/configuration-store-impl/testSrc/BinaryXmlOutputterTest.kt
@@ -18,7 +18,7 @@ class BinaryXmlOutputterTest {
private fun test(xml: String) {
val byteOut = BufferExposingByteArrayOutputStream()
byteOut.use {
- writeElement(loadElement(xml), it)
+ serializeElementToBinary(loadElement(xml), it)
}
val xmlAfter = JDOMUtil.writeElement(byteOut.toByteArray().inputStream().use { readElement(it) })
diff --git a/platform/core-api/src/com/intellij/openapi/options/scheme.kt b/platform/core-api/src/com/intellij/openapi/options/scheme.kt
index 6df367a18764..b28299a033fa 100644
--- a/platform/core-api/src/com/intellij/openapi/options/scheme.kt
+++ b/platform/core-api/src/com/intellij/openapi/options/scheme.kt
@@ -46,9 +46,13 @@ interface SchemeExtensionProvider {
val isUpgradeNeeded: Boolean
}
-
interface SchemeDataHolder {
+ /**
+ * You should call updateDigest() after read on init.
+ */
fun read(): Element
+
+ fun updateDigest()
}
abstract class SchemeManagerFactory {
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileManagerImpl.java
index 5e0d2fa26064..21695eb50c2f 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/InspectionProfileManagerImpl.java
@@ -193,11 +193,9 @@ public class InspectionProfileManagerImpl extends InspectionProfileManager imple
}
private void createDefaultProfile() {
- final InspectionProfileImpl defaultProfile = createSampleProfile(InspectionProfileImpl.DEFAULT_PROFILE_NAME, getDefaultProfile());
- addProfile(defaultProfile);
+ addProfile(createSampleProfile(InspectionProfileImpl.DEFAULT_PROFILE_NAME, getDefaultProfile()));
}
-
@Override
public Profile loadProfile(@NotNull String path) throws IOException, JDOMException {
final File file = new File(path);
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java
index a78b00703237..b1ec97958987 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/header/InspectionToolsConfigurable.java
@@ -353,13 +353,13 @@ public abstract class InspectionToolsConfigurable extends BaseConfigurable
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setDescription("Choose directory to store profile file");
FileChooser.chooseFile(descriptor, getProject(), wholePanel, null, file -> {
- final Element element = new Element("inspections");
+ final Element element;
try {
final SingleInspectionProfilePanel panel = getSelectedPanel();
LOG.assertTrue(panel != null);
final InspectionProfileImpl profile = getSelectedObject();
LOG.assertTrue(true);
- profile.writeExternal(element);
+ element = profile.writeExternal();
final String filePath =
FileUtil.toSystemDependentName(file.getPath()) + File.separator + FileUtil.sanitizeFileName(profile.getName()) + ".xml";
if (new File(filePath).isFile()) {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeImpl.java
index 605e5a375116..eecfddf1d415 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemeImpl.java
@@ -84,10 +84,12 @@ public class CodeStyleSchemeImpl implements CodeStyleScheme, ExternalizableSchem
@Override
public CodeStyleSettings getCodeStyleSettings() {
- if (myDataHolder != null) {
- init(myParentSchemeName == null ? null : CodeStyleSchemesImpl.getSchemeManager().findSchemeByName(myParentSchemeName), myDataHolder.read());
- myParentSchemeName = null;
+ SchemeDataHolder dataHolder = myDataHolder;
+ if (dataHolder != null) {
myDataHolder = null;
+ init(myParentSchemeName == null ? null : CodeStyleSchemesImpl.getSchemeManager().findSchemeByName(myParentSchemeName), dataHolder.read());
+ dataHolder.updateDigest();
+ myParentSchemeName = null;
}
return myCodeStyleSettings;
}
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
index ba9e0de84874..856c6ae681cc 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
@@ -107,7 +107,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
}
@NonNls
- private static final String COPYRIGHT = "copyright";
+ static final String COPYRIGHT = "copyright";
@NonNls
private static final String MODULE2COPYRIGHT = "module2copyright";
@NonNls
@@ -135,8 +135,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
try {
if (!myCopyrights.isEmpty()) {
for (CopyrightProfile copyright : myCopyrights.values()) {
- Element copyrightElement = new Element(COPYRIGHT);
- copyright.writeExternal(copyrightElement);
+ Element copyrightElement = copyright.writeExternal();
if (!JDOMUtil.isEmpty(copyrightElement)) {
state.addContent(copyrightElement);
}
@@ -291,7 +290,7 @@ public class CopyrightManager extends AbstractProjectComponent implements Persis
@NotNull
@Override
protected String getSubStateTagName() {
- return "copyright";
+ return COPYRIGHT;
}
}
}
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.java
index b0f5c50d64fb..957bbbc85c3e 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightProfile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * Copyright 2000-2016 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.
@@ -18,6 +18,8 @@ package com.maddyhome.idea.copyright;
import com.intellij.profile.ProfileEx;
import com.intellij.util.xmlb.SmartSerializer;
import com.maddyhome.idea.copyright.pattern.EntityUtil;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
public class CopyrightProfile extends ProfileEx {
@SuppressWarnings("SpellCheckingInspection")
@@ -64,4 +66,12 @@ public class CopyrightProfile extends ProfileEx {
public void setAllowReplaceKeyword(String allowReplaceKeyword) {
this.allowReplaceKeyword = allowReplaceKeyword;
}
+
+ @NotNull
+ @Override
+ public Element writeExternal() {
+ Element result = new Element(CopyrightManager.COPYRIGHT);
+ serializeInto(result, true);
+ return result;
+ }
}