diff --git a/java/idea-ui/src/com/intellij/openapi/project/impl/convertors/Convertor34.java b/java/idea-ui/src/com/intellij/openapi/project/impl/convertors/Convertor34.java index 8be1b7c74e8b..d8dd361ae2a6 100644 --- a/java/idea-ui/src/com/intellij/openapi/project/impl/convertors/Convertor34.java +++ b/java/idea-ui/src/com/intellij/openapi/project/impl/convertors/Convertor34.java @@ -27,7 +27,6 @@ import com.intellij.openapi.vfs.JarFileSystem; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; -import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -52,7 +51,7 @@ public class Convertor34 { private static final String JAVA_DOC_ROOTS_CANNOT_BE_CONVERTED = ProjectBundle.message("project.convert.javadoc.paths.error"); private static final String MULTIPLE_OUTPUT_PATHS = ProjectBundle.message("project.convert.multiple.output.paths.error"); - public static void execute(Element root, String filePath, @Nullable ArrayList conversionProblems) { + public static void execute(Element root, String filePath, @Nullable List conversionProblems) { if (filePath == null) return; if (conversionProblems == null) { @@ -122,7 +121,7 @@ public class Convertor34 { } @SuppressWarnings({"HardCodedStringLiteral"}) - private static void convertProjectFile(Element root, String filePath, ArrayList conversionProblems) { + private static void convertProjectFile(Element root, String filePath, List conversionProblems) { Element rootComponent = null; List components = root.getChildren("component"); for (final Object component1 : components) { @@ -184,7 +183,7 @@ public class Convertor34 { String name = root.getAttributeValue("name"); String url = root.getAttributeValue("url"); - if(name == null || url == null) continue; + if (name == null || url == null) continue; String filepath = VirtualFileManager.extractPath(url); @@ -203,7 +202,7 @@ public class Convertor34 { module.addContent(moduleProperties); Document moduleDocument = new Document(module); - String moduleName = (!"".equals(name) ? name : moduleDirectory.getName()); + String moduleName = (!name.isEmpty() ? name : moduleDirectory.getName()); if(moduleName.equals(mainModule)) moduleName = "web" + moduleName; try { final String modulePath = moduleDirectory.getPath() + "/" + moduleName + ModuleFileType.DOT_DEFAULT_EXTENSION; @@ -305,14 +304,14 @@ public class Convertor34 { VirtualFile classesDir = moduleDirectory.findFileByRelativePath("WEB-INF/classes"); if(classesDir != null) { - Element classes = createLibraryEntry(classesDir, module, moduleDirectory); + Element classes = createLibraryEntry(classesDir, moduleDirectory); newModuleRootManager.addContent(classes); } VirtualFile lib = moduleDirectory.findFileByRelativePath("WEB-INF/lib"); if(lib != null) { for (VirtualFile virtualFile : lib.getChildren()) { - Element libEntry = createLibraryEntry(virtualFile, module, moduleDirectory); + Element libEntry = createLibraryEntry(virtualFile, moduleDirectory); newModuleRootManager.addContent(libEntry); } } @@ -321,10 +320,10 @@ public class Convertor34 { } @SuppressWarnings({"HardCodedStringLiteral"}) - private static Element createLibraryEntry(VirtualFile file, Element module, VirtualFile moduleDirectory) { + private static Element createLibraryEntry(VirtualFile file, VirtualFile moduleDirectory) { String path = file.getPath().substring(moduleDirectory.getPath().length() + 1); if(file.getFileSystem() instanceof JarFileSystem) { - path = path + "!/"; + path += "!/"; } Element orderEntry = new Element("orderEntry"); @@ -340,7 +339,7 @@ public class Convertor34 { } private static String getModulePath(String path, String moduleDirectory) { - return "".equals(path) ? moduleDirectory : moduleDirectory + "/" + path; + return path != null && path.isEmpty() ? moduleDirectory : moduleDirectory + "/" + path; } @SuppressWarnings({"HardCodedStringLiteral"}) @@ -357,11 +356,11 @@ public class Convertor34 { modulesEntry.addContent(moduleEntry); } - private static Element convertProjectRootManager(Element projectRootManager, ArrayList conversionProblems) { + private static Element convertProjectRootManager(Element projectRootManager, List conversionProblems) { return new ProjectToModuleConverter(projectRootManager, conversionProblems).getModuleRootManager(); } - private static interface RootElementProcessor { + private interface RootElementProcessor { void processSimpleRoot(Element root); void processJdkRoot(Element root); @@ -468,9 +467,9 @@ public class Convertor34 { private final ArrayList myProjectRoots; private final List mySourceFolders; private final ArrayList myExcludeFolders; - private final ArrayList myDetectedProblems; + private final List myDetectedProblems; - private ProjectToModuleConverter(Element projectRootManager, ArrayList problems) { + private ProjectToModuleConverter(Element projectRootManager, List problems) { myProjectRootManager = projectRootManager; myModuleRootManager = new Element("component"); myModuleRootManager.setAttribute("name", "NewModuleRootManager"); @@ -553,10 +552,10 @@ public class Convertor34 { } private static void createFolders(final Element contentElement, - final Element patternFolderElement, - final List folders) { + final Element patternFolderElement, + final List folders) { for (String folder : folders) { - Element folderElement = (Element)patternFolderElement.clone(); + Element folderElement = patternFolderElement.clone(); folderElement.setAttribute("url", folder); contentElement.addContent(folderElement); } @@ -708,7 +707,7 @@ public class Convertor34 { final Element libraryElement = new Element("library"); final Element classesElement = new Element("CLASSES"); final Element rootElement = new Element("root"); - rootElement.setAttribute((Attribute)root.getAttribute("url").clone()); + rootElement.setAttribute(root.getAttribute("url").clone()); classesElement.addContent(rootElement); libraryElement.addContent(classesElement); orderEntry.addContent(libraryElement); diff --git a/platform/core-api/src/com/intellij/openapi/editor/ReadOnlyModificationException.java b/platform/core-api/src/com/intellij/openapi/editor/ReadOnlyModificationException.java index 209d7ff381d0..c83ff0de612d 100644 --- a/platform/core-api/src/com/intellij/openapi/editor/ReadOnlyModificationException.java +++ b/platform/core-api/src/com/intellij/openapi/editor/ReadOnlyModificationException.java @@ -17,7 +17,8 @@ package com.intellij.openapi.editor; import org.jetbrains.annotations.NotNull; -public class ReadOnlyModificationException extends RuntimeException { +public class + ReadOnlyModificationException extends RuntimeException { private final Document myDocument; public ReadOnlyModificationException(@NotNull Document document) { diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java index c12d68935126..f550fa1db3d0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ModuleStoreImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * 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. @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.application.ApplicationManager; @@ -44,7 +43,7 @@ import java.util.Map; import java.util.Set; public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IModuleStore { - private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.ModuleStoreImpl"); + private static final Logger LOG = Logger.getInstance(ModuleStoreImpl.class); private final ModuleImpl myModule; @@ -184,7 +183,7 @@ public class ModuleStoreImpl extends BaseFileConfigurableStoreImpl implements IM } @Override - public void setModuleFilePath(@NotNull final String filePath) { + public void setModuleFilePath(@NotNull String filePath) { final String path = filePath.replace(File.separatorChar, '/'); LocalFileSystem.getInstance().refreshAndFindFileByPath(path); final StateStorageManager storageManager = getStateStorageManager(); diff --git a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java index 4f334e1463e2..cacbafded87d 100644 --- a/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/components/impl/stores/ProjectWithModulesStoreImpl.java @@ -18,6 +18,7 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; +import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.impl.ModuleImpl; @@ -92,7 +93,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } private class ProjectWithModulesSaveSession extends ProjectSaveSession { - List myModuleSaveSessions = new SmartList(); + List myModuleSaveSessions = new SmartList(); public ProjectWithModulesSaveSession() { for (Module module : getPersistentModules()) { @@ -105,7 +106,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { public List getAllStorageFiles(boolean includingSubStructures) { List result = super.getAllStorageFiles(includingSubStructures); if (includingSubStructures) { - for (SaveSession moduleSaveSession : myModuleSaveSessions) { + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { result.addAll(moduleSaveSession.getAllStorageFiles(true)); } } @@ -121,7 +122,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } Set result = superResult.isEmpty() ? null : new THashSet(superResult); - for (SaveSession moduleSaveSession : myModuleSaveSessions) { + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { Set s = moduleSaveSession.analyzeExternalChanges(changedFiles); if (s == null) { return null; @@ -140,7 +141,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { public void finishSave() { try { Throwable first = null; - for (SaveSession moduleSaveSession : myModuleSaveSessions) { + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { try { moduleSaveSession.finishSave(); } @@ -163,7 +164,7 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { @Override public void reset() { try { - for (SaveSession moduleSaveSession : myModuleSaveSessions) { + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { moduleSaveSession.reset(); } } @@ -173,16 +174,17 @@ public class ProjectWithModulesStoreImpl extends ProjectStoreImpl { } @Override - protected void beforeSave() { - super.beforeSave(); - for (SaveSession moduleSaveSession : myModuleSaveSessions) { - moduleSaveSession.save(); + protected void beforeSave(@NotNull List> readonlyFiles) { + super.beforeSave(readonlyFiles); + + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { + moduleSaveSession.save(readonlyFiles); } } @Override protected void collectSubFilesToSave(@NotNull List result) { - for (SaveSession moduleSaveSession : myModuleSaveSessions) { + for (ComponentSaveSession moduleSaveSession : myModuleSaveSessions) { result.addAll(moduleSaveSession.getAllStorageFilesToSave(true)); } } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java index 84040d4dcc62..cde0adcd15b3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java @@ -410,7 +410,7 @@ public class ClasspathStorage implements StateStorage { } @Override - public void save() throws StateStorageException { + public void save() { assert mySession == this; ClasspathStorage.this.save(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java index b281671f74df..d43d446de757 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/BaseFileConfigurableStoreImpl.java @@ -17,31 +17,33 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.*; import com.intellij.openapi.project.impl.ProjectManagerImpl; +import com.intellij.util.SmartList; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.IOException; -import java.util.ArrayList; +import java.util.List; import java.util.Set; abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl { @NonNls protected static final String VERSION_OPTION = "version"; @NonNls public static final String ATTRIBUTE_NAME = "name"; + + private static final List ourConversionProblemsStorage = new SmartList(); + private final ComponentManager myComponentManager; - private static final ArrayList ourConversionProblemsStorage = new ArrayList(); private final DefaultsStateStorage myDefaultsStateStorage; private StateStorageManager myStateStorageManager; - - protected BaseFileConfigurableStoreImpl(final ComponentManager componentManager) { + protected BaseFileConfigurableStoreImpl(@NotNull ComponentManager componentManager) { myComponentManager = componentManager; - final PathMacroManager pathMacroManager = PathMacroManager.getInstance(myComponentManager); - myDefaultsStateStorage = new DefaultsStateStorage(pathMacroManager); + myDefaultsStateStorage = new DefaultsStateStorage(PathMacroManager.getInstance(myComponentManager)); } - public synchronized ComponentManager getComponentManager() { + @NotNull + public ComponentManager getComponentManager() { return myComponentManager; } @@ -109,7 +111,7 @@ abstract class BaseFileConfigurableStoreImpl extends ComponentStoreImpl { protected abstract XmlElementStorage getMainStorage(); @Nullable - static ArrayList getConversionProblemsStorage() { + static List getConversionProblemsStorage() { return ourConversionProblemsStorage; } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 616515c8daf2..ab03071858b5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -22,6 +22,8 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ex.ApplicationManagerEx; import com.intellij.openapi.components.*; import com.intellij.openapi.components.impl.ComponentManagerImpl; +import com.intellij.openapi.components.store.ComponentSaveSession; +import com.intellij.openapi.components.store.ReadOnlyModificationException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.PluginId; import com.intellij.openapi.project.Project; @@ -90,7 +92,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { @Override @NotNull - public SaveSession startSave() { + public ComponentSaveSession startSave() { SaveSessionImpl session = createSaveSession(); try { session.commit(); @@ -118,7 +120,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { return new SaveSessionImpl(); } - public void finishSave(@NotNull final SaveSession saveSession) { + public void finishSave(@NotNull final ComponentSaveSession saveSession) { assert mySession == saveSession; mySession.finishSave(); mySession = null; @@ -336,7 +338,16 @@ public abstract class ComponentStoreImpl implements IComponentStore { return null; } - protected class SaveSessionImpl implements SaveSession { + protected static void executeSave(@NotNull StateStorageManager.SaveSession saveSession, @NotNull List> readonlyFiles) { + try { + saveSession.save(); + } + catch (ReadOnlyModificationException e) { + readonlyFiles.add(Pair.create(saveSession, e.getFile())); + } + } + + protected class SaveSessionImpl implements ComponentSaveSession { protected StateStorageManager.SaveSession myStorageManagerSaveSession; public SaveSessionImpl() { @@ -351,7 +362,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { @NotNull @Override - public SaveSession save() { + public ComponentSaveSession save(@NotNull List> readonlyFiles) { SettingsSavingComponent[] settingsComponents = mySettingsSavingComponents.toArray(new SettingsSavingComponent[mySettingsSavingComponents.size()]); for (SettingsSavingComponent settingsSavingComponent : settingsComponents) { @@ -363,7 +374,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { } } - myStorageManagerSaveSession.save(); + executeSave(myStorageManagerSaveSession, readonlyFiles); return this; } @@ -391,7 +402,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { } } - protected void commit() throws StateStorageException { + protected void commit() { final StateStorageManager storageManager = getStateStorageManager(); final StateStorageManager.ExternalizationSession session = storageManager.startExternalization(); @@ -471,7 +482,7 @@ public abstract class ComponentStoreImpl implements IComponentStore { @Nullable protected final Collection reload(@NotNull Set> changedFiles, @NotNull MessageBus messageBus) { - SaveSession saveSession = startSave(); + ComponentSaveSession saveSession = startSave(); Set componentNames; try { componentNames = saveSession.analyzeExternalChanges(changedFiles); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java index 47e184936837..cc6cc7986b8c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DefaultProjectStoreImpl.java @@ -162,7 +162,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl { @NotNull @Override - public SaveSession startSave(@NotNull final ExternalizationSession externalizationSession) { + public SaveSession startSave(@NotNull ExternalizationSession externalizationSession) { return new MySaveSession(storage, externalizationSession); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java index a8df62ad4dab..7c1153848f77 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/DirectoryBasedStorage.java @@ -25,7 +25,10 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.WriteExternalException; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.util.text.StringUtilRt; -import com.intellij.openapi.vfs.*; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileAdapter; +import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.tracker.VirtualFileTracker; import com.intellij.util.SmartList; import com.intellij.util.containers.SmartHashSet; @@ -168,7 +171,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable { public void dispose() { } - private class MySaveSession implements SaveSession, SafeWriteRequestor { + private class MySaveSession implements SaveSession { private final DirectoryStorageData myStorageData; private final TrackingPathMacroSubstitutor myPathMacroSubstitutor; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java index b0e3b0520b14..6c8cfd22cb84 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IComponentStore.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * 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. @@ -15,17 +15,12 @@ */ package com.intellij.openapi.components.impl.stores; -import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorageException; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.components.store.ComponentSaveSession; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; import java.util.Collection; -import java.util.List; import java.util.Set; public interface IComponentStore { @@ -55,23 +50,5 @@ public interface IComponentStore { } @NotNull - SaveSession startSave(); - - interface SaveSession { - @NotNull - List getAllStorageFilesToSave(boolean includingSubStructures); - - @NotNull - SaveSession save(); - - void finishSave(); - - void reset(); - - @Nullable - Set analyzeExternalChanges(@NotNull Set> changedFiles); - - @NotNull - List getAllStorageFiles(final boolean includingSubStructures); - } + ComponentSaveSession startSave(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IModuleStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IModuleStore.java index bee6e771f505..d9c7f759d085 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IModuleStore.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IModuleStore.java @@ -20,8 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public interface IModuleStore extends IComponentStore { - - void setModuleFilePath(final String filePath); + void setModuleFilePath(@NotNull String filePath); @Nullable VirtualFile getModuleFile(); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java index 83877f76aaab..0993ed9db154 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java @@ -19,10 +19,9 @@ import com.intellij.CommonBundle; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.highlighter.WorkspaceFileType; import com.intellij.notification.NotificationsManager; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.application.*; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.fileTypes.FileTypeManager; @@ -32,7 +31,6 @@ import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.project.impl.ProjectManagerImpl; import com.intellij.openapi.ui.Messages; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; @@ -51,7 +49,6 @@ import org.jetbrains.annotations.Nullable; import java.io.*; import java.lang.annotation.Annotation; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.Set; @@ -87,7 +84,7 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject name + OLD_PROJECT_SUFFIX + projectFile.getExtension()); if (Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) != Messages.YES) return false; - final ArrayList conversionProblems = getConversionProblemsStorage(); + List conversionProblems = getConversionProblemsStorage(); if (conversionProblems != null && !conversionProblems.isEmpty()) { StringBuilder buffer = new StringBuilder(); buffer.append(ProjectBundle.message("project.convert.problems.detected")); @@ -494,97 +491,57 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject @NotNull @Override - public SaveSession save() { + public ComponentSaveSession save(@NotNull List> readonlyFiles) { ProjectImpl.UnableToSaveProjectNotification[] notifications = NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, myProject); if (notifications.length > 0) { throw new SaveCancelledException(); } - ReadonlyStatusHandler.OperationStatus operationStatus = ensureConfigFilesWritable(); - if (operationStatus == null) { - throw new StateStorageException(); - } - else if (operationStatus.hasReadonlyFiles()) { - ProjectImpl.dropUnableToSaveProjectNotification(myProject, operationStatus.getReadonlyFiles()); - throw new SaveCancelledException(); + beforeSave(readonlyFiles); + + super.save(readonlyFiles); + + if (!readonlyFiles.isEmpty()) { + ReadonlyStatusHandler.OperationStatus status; + AccessToken token = ReadAction.start(); + try { + status = ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(getFilesList(readonlyFiles)); + } + finally { + token.finish(); + } + + if (status.hasReadonlyFiles()) { + ProjectImpl.dropUnableToSaveProjectNotification(myProject, status.getReadonlyFiles()); + throw new SaveCancelledException(); + } + else { + readonlyFiles.clear(); + for (Pair entry : readonlyFiles) { + executeSave(entry.first, readonlyFiles); + } + + if (!readonlyFiles.isEmpty()) { + ProjectImpl.dropUnableToSaveProjectNotification(myProject, getFilesList(readonlyFiles)); + throw new SaveCancelledException(); + } + } } - beforeSave(); - super.save(); return this; } - protected void beforeSave() { + @NotNull + private VirtualFile[] getFilesList(List> readonlyFiles) { + final VirtualFile[] files = new VirtualFile[readonlyFiles.size()]; + for (int i = 0, size = readonlyFiles.size(); i < size; i++) { + files[i] = readonlyFiles.get(i).second; + } + return files; } - private ReadonlyStatusHandler.OperationStatus ensureConfigFilesWritable() { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public ReadonlyStatusHandler.OperationStatus compute() { - List filesToSave; - try { - filesToSave = getAllStorageFilesToSave(true); - Iterator iterator = filesToSave.iterator(); - while (iterator.hasNext()) { - if (!iterator.next().exists()) { - iterator.remove(); - } - } - } - catch (Exception e) { - LOG.error(e); - return null; - } - - List readonlyFiles = new ArrayList(); - - if (myProject.isToSaveProjectName()) { - final VirtualFile baseDir = getProjectBaseDir(); - if (baseDir != null && baseDir.isValid()) { - filesToSave.add(new File(new File(baseDir.getPath(), Project.DIRECTORY_STORE_FOLDER), ProjectImpl.NAME_FILE)); - } - } - - for (File file : filesToSave) { - final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file); - if (virtualFile != null) { - virtualFile.refresh(false, false); - if (virtualFile.isValid() && !virtualFile.isWritable()) { - readonlyFiles.add(virtualFile); - } - } - } - - if (readonlyFiles.isEmpty()) { - final VirtualFile projectBaseDir = getProjectBaseDir(); - if (projectBaseDir != null && projectBaseDir.isValid()) { - if (!projectBaseDir.isWritable()) { - readonlyFiles.add(projectBaseDir); - } - - final LocalFileSystem instance = LocalFileSystem.getInstance(); - final VirtualFile ideaDir1 = - instance.findFileByIoFile(new File(projectBaseDir.getPath(), Project.DIRECTORY_STORE_FOLDER)); - if (ideaDir1 != null && ideaDir1.isValid()) { - if (!ideaDir1.isWritable()) { - readonlyFiles.add(ideaDir1); - } - } else { - final VirtualFile ideaDir2 = - instance.findFileByIoFile(new File(new File(projectBaseDir.getPath()).getParent(), Project.DIRECTORY_STORE_FOLDER)); - if (ideaDir2 != null && ideaDir2.isValid()) { - if (!ideaDir2.isWritable()) { - readonlyFiles.add(ideaDir2); - } - } - } - } - } - - return ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(readonlyFiles); - } - }); + protected void beforeSave(@NotNull List> readonlyFiles) { } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index 52c44f57d5b4..04aa057f2254 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -21,6 +21,7 @@ import com.intellij.notification.NotificationType; import com.intellij.notification.NotificationsManager; import com.intellij.openapi.application.*; import com.intellij.openapi.components.*; +import com.intellij.openapi.components.store.ReadOnlyModificationException; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.DocumentRunnable; import com.intellij.openapi.project.Project; @@ -173,6 +174,14 @@ public class StorageUtil { } return virtualFile; } + catch (FileNotFoundException e) { + if (virtualFile == null) { + throw e; + } + else { + throw new ReadOnlyModificationException(virtualFile); + } + } finally { token.finish(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java index 97d449c9acaa..20735fc2775e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StoreUtil.java @@ -15,8 +15,14 @@ */ package com.intellij.openapi.components.impl.stores; +import com.intellij.openapi.components.store.ComponentSaveSession; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * @author yole */ @@ -25,10 +31,11 @@ public class StoreUtil { } public static void doSave(@NotNull IComponentStore stateStore) { - IComponentStore.SaveSession session = null; + ComponentSaveSession session = null; try { session = stateStore.startSave(); - session.save(); + List> readonlyFiles = new SmartList>(); + session.save(readonlyFiles); } finally { if (session != null) { diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java index 819e1e4dae80..4cdd91efe525 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/XmlElementStorage.java @@ -23,7 +23,6 @@ import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.JDOMUtil; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.WriteExternalException; -import com.intellij.openapi.vfs.SafeWriteRequestor; import com.intellij.openapi.vfs.VirtualFile; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -217,7 +216,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { private static SaveSession createNullSession() { return new SaveSession(){ @Override - public void save() throws StateStorageException { + public void save() { } @Override @@ -320,7 +319,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { return element; } - protected abstract class MySaveSession implements SaveSession, SafeWriteRequestor { + protected abstract class MySaveSession implements SaveSession { final StorageData myStorageData; private Element myElementToSave; @@ -380,7 +379,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { } @Override - public final void save() throws StateStorageException { + public final void save() { assert mySession == this; if (myBlockSavingTheContent) { @@ -392,27 +391,17 @@ public abstract class XmlElementStorage implements StateStorage, Disposable { if (myStreamProvider != null && myStreamProvider.isEnabled() && (myProviderUpToDateHash == -1 || myProviderUpToDateHash != hash)) { try { saveForProvider(); - } - catch (IOException e) { - LOG.warn(e); - } - finally { myProviderUpToDateHash = hash; } + catch (Throwable e) { + LOG.error(e); + } } } finally { - saveLocally(hash); - } - } - - private void saveLocally(int hash) { - try { if (!(myUpToDateHash != -1 && myUpToDateHash == hash) && _needsSave(hash)) { doSave(); } - } - finally { myUpToDateHash = hash; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java b/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java new file mode 100644 index 000000000000..70d5118bc1fc --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/components/store/ComponentSaveSession.java @@ -0,0 +1,45 @@ +/* + * 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.openapi.components.store; + +import com.intellij.openapi.components.StateStorage; +import com.intellij.openapi.components.impl.stores.StateStorageManager; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.List; +import java.util.Set; + +public interface ComponentSaveSession { + @NotNull + List getAllStorageFilesToSave(boolean includingSubStructures); + + @NotNull + ComponentSaveSession save(@NotNull List> readonlyFiles); + + void finishSave(); + + void reset(); + + @Nullable + Set analyzeExternalChanges(@NotNull Set> changedFiles); + + @NotNull + List getAllStorageFiles(final boolean includingSubStructures); +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java b/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java new file mode 100644 index 000000000000..f1257d87e4a1 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/components/store/ReadOnlyModificationException.java @@ -0,0 +1,32 @@ +/* + * 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.openapi.components.store; + +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +public final class ReadOnlyModificationException extends RuntimeException { + private final VirtualFile myFile; + + public ReadOnlyModificationException(@NotNull VirtualFile file) { + myFile = file; + } + + @NotNull + public VirtualFile getFile() { + return myFile; + } +} \ No newline at end of file diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index 25866edd2f22..2c499174f563 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -32,9 +32,9 @@ import com.intellij.openapi.components.ExportableApplicationComponent; import com.intellij.openapi.components.StateStorage; import com.intellij.openapi.components.StateStorageException; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; -import com.intellij.openapi.components.impl.stores.IComponentStore; import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.components.impl.stores.XmlElementStorage; +import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.progress.*; @@ -918,7 +918,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements NamedJDOMExt final String location = projectImpl.getPresentableUrl(); final List original; try { - IComponentStore.SaveSession saveSession = projectImpl.getStateStore().startSave(); + ComponentSaveSession saveSession = projectImpl.getStateStore().startSave(); original = saveSession.getAllStorageFiles(true); saveSession.finishSave(); } diff --git a/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java b/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java index 1636c2993273..18636de39d9d 100644 --- a/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java +++ b/platform/projectModel-api/src/com/intellij/openapi/components/StateStorage.java @@ -51,7 +51,7 @@ public interface StateStorage { } interface SaveSession { - void save() throws StateStorageException; + void save(); /** * Get changed component names diff --git a/platform/testFramework/src/com/intellij/mock/MockProjectStore.java b/platform/testFramework/src/com/intellij/mock/MockProjectStore.java index 046862965f68..d4ea6d3fe32e 100644 --- a/platform/testFramework/src/com/intellij/mock/MockProjectStore.java +++ b/platform/testFramework/src/com/intellij/mock/MockProjectStore.java @@ -20,6 +20,7 @@ import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.impl.stores.IProjectStore; import com.intellij.openapi.components.impl.stores.StateStorageManager; +import com.intellij.openapi.components.store.ComponentSaveSession; import com.intellij.openapi.project.impl.ProjectImpl; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.Pair; @@ -138,7 +139,7 @@ public class MockProjectStore implements IProjectStore { @Override @NotNull - public SaveSession startSave() { + public ComponentSaveSession startSave() { throw new UnsupportedOperationException("Method startSave not implemented in " + getClass()); }