mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
extract ProjectSaveSessionProducerManager
This commit is contained in:
@@ -135,7 +135,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
|
||||
beforeSaveComponents(errors, readonlyFiles)
|
||||
|
||||
val saveSessionProducerManager = if (components.isEmpty()) null else SaveSessionProducerManager()
|
||||
val saveSessionProducerManager = if (components.isEmpty()) null else createSaveSessionProducerManager()
|
||||
if (saveSessionProducerManager != null) {
|
||||
saveComponents(isForce, saveSessionProducerManager, errors)
|
||||
}
|
||||
@@ -148,7 +148,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
|
||||
if (saveSessionProducerManager != null) {
|
||||
doSave(saveSessionProducerManager, readonlyFiles, errors)
|
||||
saveSessionProducerManager.save(readonlyFiles, errors)
|
||||
}
|
||||
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
@@ -224,7 +224,7 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
override fun saveApplicationComponent(component: PersistentStateComponent<*>) {
|
||||
val stateSpec = StoreUtil.getStateSpec(component)
|
||||
LOG.info("saveApplicationComponent is called for ${stateSpec.name}")
|
||||
val externalizationSession = SaveSessionProducerManager()
|
||||
val externalizationSession = createSaveSessionProducerManager()
|
||||
commitComponent(externalizationSession, ComponentInfoImpl(component, stateSpec), null)
|
||||
val absolutePath = Paths.get(storageManager.expandMacros(findNonDeprecated(stateSpec.storages).path)).toAbsolutePath().toString()
|
||||
runUndoTransparentWriteAction {
|
||||
@@ -244,6 +244,8 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
}
|
||||
|
||||
internal open fun createSaveSessionProducerManager() = SaveSessionProducerManager()
|
||||
|
||||
private fun commitComponent(session: SaveSessionProducerManager, info: ComponentInfo, componentName: String?) {
|
||||
val component = info.component
|
||||
@Suppress("DEPRECATION")
|
||||
@@ -280,10 +282,6 @@ abstract class ComponentStoreImpl : IComponentStore {
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun doSave(saveSession: SaveExecutor, readonlyFiles: MutableList<SaveSessionAndFile> = arrayListOf(), errors: MutableList<Throwable>) {
|
||||
saveSession.save(readonlyFiles, errors)
|
||||
}
|
||||
|
||||
private fun initJdomExternalizable(@Suppress("DEPRECATION") component: JDOMExternalizable, componentName: String): String? {
|
||||
doAddComponent(componentName, component, null)
|
||||
|
||||
@@ -601,37 +599,4 @@ private fun notifyUnknownMacros(store: IComponentStore, project: Project, compon
|
||||
LOG.debug("Reporting unknown path macros $macros in component $componentName")
|
||||
doNotify(macros, project, Collections.singletonMap(substitutor, store))
|
||||
}, project.disposed)
|
||||
}
|
||||
|
||||
interface SaveExecutor {
|
||||
/**
|
||||
* @return was something really saved
|
||||
*/
|
||||
fun save(readonlyFiles: MutableList<SaveSessionAndFile> = SmartList(), errors: MutableList<Throwable>): Boolean
|
||||
}
|
||||
|
||||
private class SaveSessionProducerManager : SaveExecutor {
|
||||
private val producers = LinkedHashMap<StateStorage, SaveSessionProducer>()
|
||||
|
||||
fun getProducer(storage: StateStorage): SaveSessionProducer? {
|
||||
var producer = producers.get(storage)
|
||||
if (producer == null) {
|
||||
producer = storage.createSaveSessionProducer() ?: return null
|
||||
producers.put(storage, producer)
|
||||
}
|
||||
return producer
|
||||
}
|
||||
|
||||
override fun save(readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>): Boolean {
|
||||
if (producers.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
var changed = false
|
||||
for (session in producers.values) {
|
||||
executeSave(session.createSaveSession() ?: continue, readonlyFiles, errors)
|
||||
changed = true
|
||||
}
|
||||
return changed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.notification.NotificationsManager
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
import com.intellij.openapi.components.impl.stores.IComponentStore
|
||||
import com.intellij.openapi.components.impl.stores.SaveSessionAndFile
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl
|
||||
import com.intellij.openapi.vfs.ReadonlyStatusHandler
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.util.containers.mapSmart
|
||||
import com.intellij.util.lang.CompoundRuntimeException
|
||||
|
||||
internal class ProjectSaveSessionProducerManager(private val project: Project) : SaveSessionProducerManager() {
|
||||
override fun save(readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>): Boolean {
|
||||
val isChanged = super.save(readonlyFiles, errors)
|
||||
|
||||
val notifications = getUnableToSaveNotifications()
|
||||
if (readonlyFiles.isEmpty()) {
|
||||
notifications.forEach { it.expire() }
|
||||
return isChanged
|
||||
}
|
||||
|
||||
if (!notifications.isEmpty()) {
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
|
||||
val status = runReadAction {
|
||||
ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(getFilesList(readonlyFiles))
|
||||
}
|
||||
if (status.hasReadonlyFiles()) {
|
||||
dropUnableToSaveProjectNotification(project, status.readonlyFiles.toList())
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
|
||||
val oldList = readonlyFiles.toTypedArray()
|
||||
readonlyFiles.clear()
|
||||
for (entry in oldList) {
|
||||
executeSave(entry.session, readonlyFiles, errors)
|
||||
}
|
||||
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
dropUnableToSaveProjectNotification(project, getFilesList(readonlyFiles))
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
|
||||
return isChanged
|
||||
}
|
||||
|
||||
private fun dropUnableToSaveProjectNotification(project: Project, readOnlyFiles: List<VirtualFile>) {
|
||||
val notifications = getUnableToSaveNotifications()
|
||||
if (notifications.isEmpty()) {
|
||||
Notifications.Bus.notify(
|
||||
ProjectManagerImpl.UnableToSaveProjectNotification(project, readOnlyFiles), project)
|
||||
}
|
||||
else {
|
||||
notifications[0].setFiles(readOnlyFiles)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getUnableToSaveNotifications(): Array<out ProjectManagerImpl.UnableToSaveProjectNotification> {
|
||||
return NotificationsManager.getNotificationsManager()
|
||||
.getNotificationsOfType(ProjectManagerImpl.UnableToSaveProjectNotification::class.java, project)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFilesList(readonlyFiles: List<SaveSessionAndFile>) = readonlyFiles.mapSmart { it.file }
|
||||
@@ -3,8 +3,6 @@ package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.ide.highlighter.ProjectFileType
|
||||
import com.intellij.ide.highlighter.WorkspaceFileType
|
||||
import com.intellij.notification.Notifications
|
||||
import com.intellij.notification.NotificationsManager
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.invokeAndWaitIfNeed
|
||||
import com.intellij.openapi.application.runReadAction
|
||||
@@ -20,7 +18,6 @@ import com.intellij.openapi.project.ProjectCoreUtil
|
||||
import com.intellij.openapi.project.ex.ProjectNameProvider
|
||||
import com.intellij.openapi.project.getProjectCachePath
|
||||
import com.intellij.openapi.project.impl.ProjectImpl
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl.UnableToSaveProjectNotification
|
||||
import com.intellij.openapi.project.impl.ProjectStoreClassProvider
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.util.io.FileUtilRt
|
||||
@@ -33,9 +30,7 @@ import com.intellij.util.PathUtilRt
|
||||
import com.intellij.util.SmartList
|
||||
import com.intellij.util.containers.computeIfAny
|
||||
import com.intellij.util.containers.isNullOrEmpty
|
||||
import com.intellij.util.containers.mapSmart
|
||||
import com.intellij.util.io.*
|
||||
import com.intellij.util.lang.CompoundRuntimeException
|
||||
import com.intellij.util.text.nullize
|
||||
import java.nio.file.AccessDeniedException
|
||||
import java.nio.file.Path
|
||||
@@ -333,52 +328,9 @@ private open class ProjectStoreImpl(project: Project, private val pathMacroManag
|
||||
super.beforeSaveComponents(errors, readonlyFiles)
|
||||
}
|
||||
|
||||
override fun doSave(saveSession: SaveExecutor, readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>) {
|
||||
super.doSave(saveSession, readonlyFiles, errors)
|
||||
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification::class.java, project)
|
||||
if (readonlyFiles.isEmpty()) {
|
||||
notifications.forEach { it.expire() }
|
||||
return
|
||||
}
|
||||
|
||||
if (!notifications.isEmpty()) {
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
|
||||
val status = runReadAction { ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(getFilesList(readonlyFiles)) }
|
||||
if (status.hasReadonlyFiles()) {
|
||||
dropUnableToSaveProjectNotification(project, status.readonlyFiles.toList())
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
|
||||
val oldList = readonlyFiles.toTypedArray()
|
||||
readonlyFiles.clear()
|
||||
for (entry in oldList) {
|
||||
executeSave(entry.session, readonlyFiles, errors)
|
||||
}
|
||||
|
||||
CompoundRuntimeException.throwIfNotEmpty(errors)
|
||||
|
||||
if (!readonlyFiles.isEmpty()) {
|
||||
dropUnableToSaveProjectNotification(project, getFilesList(readonlyFiles))
|
||||
throw IComponentStore.SaveCancelledException()
|
||||
}
|
||||
}
|
||||
final override fun createSaveSessionProducerManager() = ProjectSaveSessionProducerManager(project)
|
||||
}
|
||||
|
||||
private fun dropUnableToSaveProjectNotification(project: Project, readOnlyFiles: List<VirtualFile>) {
|
||||
val notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification::class.java, project)
|
||||
if (notifications.isEmpty()) {
|
||||
Notifications.Bus.notify(UnableToSaveProjectNotification(project, readOnlyFiles), project)
|
||||
}
|
||||
else {
|
||||
notifications[0].myFiles = readOnlyFiles
|
||||
}
|
||||
}
|
||||
|
||||
private fun getFilesList(readonlyFiles: List<SaveSessionAndFile>) = readonlyFiles.mapSmart { it.file }
|
||||
|
||||
private class ProjectWithModulesStoreImpl(project: Project, pathMacroManager: PathMacroManager) : ProjectStoreImpl(project, pathMacroManager) {
|
||||
override fun beforeSaveComponents(errors: MutableList<Throwable>, readonlyFiles: MutableList<SaveSessionAndFile>) {
|
||||
super.beforeSaveComponents(errors, readonlyFiles)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.configurationStore
|
||||
|
||||
import com.intellij.openapi.components.StateStorage
|
||||
import com.intellij.openapi.components.impl.stores.SaveSessionAndFile
|
||||
import com.intellij.util.SmartList
|
||||
import java.util.*
|
||||
|
||||
interface SaveExecutor {
|
||||
/**
|
||||
* @return was something really saved
|
||||
*/
|
||||
fun save(readonlyFiles: MutableList<SaveSessionAndFile> = SmartList(), errors: MutableList<Throwable>): Boolean
|
||||
}
|
||||
|
||||
internal open class SaveSessionProducerManager : SaveExecutor {
|
||||
private val producers = LinkedHashMap<StateStorage, SaveSessionProducer>()
|
||||
|
||||
fun getProducer(storage: StateStorage): SaveSessionProducer? {
|
||||
var producer = producers.get(storage)
|
||||
if (producer == null) {
|
||||
producer = storage.createSaveSessionProducer() ?: return null
|
||||
producers.put(storage, producer)
|
||||
}
|
||||
return producer
|
||||
}
|
||||
|
||||
override fun save(readonlyFiles: MutableList<SaveSessionAndFile>, errors: MutableList<Throwable>): Boolean {
|
||||
if (producers.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
|
||||
var isChanged = false
|
||||
for (session in producers.values) {
|
||||
executeSave(session.createSaveSession() ?: continue, readonlyFiles, errors)
|
||||
isChanged = true
|
||||
}
|
||||
return isChanged
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -887,7 +887,12 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable {
|
||||
|
||||
public static class UnableToSaveProjectNotification extends Notification {
|
||||
private Project myProject;
|
||||
public List<VirtualFile> myFiles;
|
||||
|
||||
private List<VirtualFile> myFiles;
|
||||
|
||||
public void setFiles(@NotNull List<VirtualFile> files) {
|
||||
myFiles = files;
|
||||
}
|
||||
|
||||
public UnableToSaveProjectNotification(@NotNull final Project project, @NotNull List<VirtualFile> readOnlyFiles) {
|
||||
super("Project Settings", "Could not save project", "Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
|
||||
|
||||
Reference in New Issue
Block a user