mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DirectoryBasedStorage — fix analyzeExternalChangesAndUpdateIfNeed
This commit is contained in:
+1
-2
@@ -28,7 +28,6 @@ import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.roots.ModuleRootModel;
|
||||
import com.intellij.openapi.roots.impl.ModuleRootManagerImpl;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -176,7 +175,7 @@ public class ClasspathStorage implements StateStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull Set<String> result) {
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> result) {
|
||||
}
|
||||
|
||||
public void save() throws StateStorageException {
|
||||
|
||||
+23
-16
@@ -27,6 +27,7 @@ import com.intellij.openapi.components.StateStorage.SaveSession;
|
||||
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.components.store.StateStorageBase;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -39,6 +40,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import com.intellij.util.containers.SmartHashSet;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -428,14 +430,14 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public final Collection<String> reload(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles) {
|
||||
public final Collection<String> reload(@NotNull MultiMap<StateStorage, VirtualFile> changedStorages) {
|
||||
Set<String> componentNames = new SmartHashSet<String>();
|
||||
for (Pair<VirtualFile, StateStorage> pair : changedFiles) {
|
||||
StateStorage storage = pair.second;
|
||||
|
||||
for (StateStorage storage : changedStorages.keySet()) {
|
||||
try {
|
||||
// we must update (reload in-memory storage data) even if non-reloadable component will be detected later
|
||||
// not saved -> user does own modification -> new (on disk) state will be overwritten and not applied
|
||||
storage.analyzeExternalChangesAndUpdateIfNeed(changedFiles, componentNames);
|
||||
storage.analyzeExternalChangesAndUpdateIfNeed(changedStorages.get(storage), componentNames);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
LOG.error(e);
|
||||
@@ -475,13 +477,18 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ReloadComponentStoreStatus reloadStore(@NotNull Collection<Pair<VirtualFile, StateStorage>> causes, @NotNull IComponentStore.Reloadable store) {
|
||||
public static ReloadComponentStoreStatus reloadStore(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedStorages, @NotNull IComponentStore.Reloadable store) {
|
||||
MultiMap<StateStorage, VirtualFile> storageToFiles = MultiMap.createLinkedSet();
|
||||
for (Pair<VirtualFile, StateStorage> pair : changedStorages) {
|
||||
storageToFiles.putValue(pair.second, pair.first);
|
||||
}
|
||||
|
||||
Collection<String> notReloadableComponents;
|
||||
boolean willBeReloaded = false;
|
||||
try {
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
notReloadableComponents = store.reload(causes);
|
||||
notReloadableComponents = store.reload(storageToFiles);
|
||||
}
|
||||
catch (Throwable e) {
|
||||
Messages.showWarningDialog(ProjectBundle.message("project.reload.failed", e.getMessage()),
|
||||
@@ -496,14 +503,14 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
return ReloadComponentStoreStatus.SUCCESS;
|
||||
}
|
||||
|
||||
willBeReloaded = askToRestart(store, notReloadableComponents, causes);
|
||||
willBeReloaded = askToRestart(store, notReloadableComponents, changedStorages);
|
||||
return willBeReloaded ? ReloadComponentStoreStatus.RESTART_AGREED : ReloadComponentStoreStatus.RESTART_CANCELLED;
|
||||
}
|
||||
finally {
|
||||
if (!willBeReloaded) {
|
||||
for (Pair<VirtualFile, StateStorage> cause : causes) {
|
||||
if (cause.second instanceof XmlElementStorage) {
|
||||
((XmlElementStorage)cause.second).enableSaving();
|
||||
for (StateStorage storage : storageToFiles.keySet()) {
|
||||
if (storage instanceof StateStorageBase) {
|
||||
((StateStorageBase)storage).enableSaving();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -513,7 +520,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
// used in settings repository plugin
|
||||
public static boolean askToRestart(@NotNull Reloadable store,
|
||||
@NotNull Collection<String> notReloadableComponents,
|
||||
@Nullable Collection<Pair<VirtualFile, StateStorage>> causes) {
|
||||
@Nullable Collection<Pair<VirtualFile, StateStorage>> changedStorages) {
|
||||
StringBuilder message = new StringBuilder();
|
||||
String storeName = store instanceof IApplicationStore ? "Application" : "Project";
|
||||
message.append(storeName).append(' ');
|
||||
@@ -540,11 +547,11 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
|
||||
|
||||
if (Messages.showYesNoDialog(message.toString(),
|
||||
storeName + " Files Changed", Messages.getQuestionIcon()) == Messages.YES) {
|
||||
if (causes != null) {
|
||||
for (Pair<VirtualFile, StateStorage> cause : causes) {
|
||||
StateStorage stateStorage = cause.getSecond();
|
||||
if (stateStorage instanceof XmlElementStorage) {
|
||||
((XmlElementStorage)stateStorage).disableSaving();
|
||||
if (changedStorages != null) {
|
||||
for (Pair<VirtualFile, StateStorage> cause : changedStorages) {
|
||||
StateStorage storage = cause.getSecond();
|
||||
if (storage instanceof StateStorageBase) {
|
||||
((StateStorageBase)storage).disableSaving();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class DefaultProjectStoreImpl extends ProjectStoreImpl {
|
||||
|
||||
ComponentManager componentManager = getComponentManager();
|
||||
final Element element = _d;
|
||||
final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, PathMacroManager.getInstance(componentManager).createTrackingSubstitutor(), componentManager,
|
||||
final XmlElementStorage storage = new XmlElementStorage("", RoamingType.DISABLED, PathMacroManager.getInstance(componentManager).createTrackingSubstitutor(),
|
||||
ROOT_TAG_NAME, null,
|
||||
ComponentVersionProvider.EMPTY) {
|
||||
@Override
|
||||
|
||||
+1
-3
@@ -20,7 +20,6 @@ import com.intellij.openapi.components.PathMacroManager;
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.StateStorageException;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.xmlb.JDOMXIncluder;
|
||||
import org.jdom.Document;
|
||||
@@ -38,7 +37,6 @@ import java.util.Set;
|
||||
class DefaultsStateStorage implements StateStorage {
|
||||
private final PathMacroManager myPathMacroManager;
|
||||
|
||||
|
||||
public DefaultsStateStorage(@Nullable final PathMacroManager pathMacroManager) {
|
||||
myPathMacroManager = pathMacroManager;
|
||||
}
|
||||
@@ -92,6 +90,6 @@ class DefaultsStateStorage implements StateStorage {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull Set<String> result) {
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> result) {
|
||||
}
|
||||
}
|
||||
|
||||
+105
-140
@@ -16,21 +16,20 @@
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.components.store.StateStorageBase;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
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.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.containers.SmartHashSet;
|
||||
import gnu.trove.TObjectObjectProcedure;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -42,74 +41,63 @@ import java.util.Set;
|
||||
|
||||
//todo: support missing plugins
|
||||
//todo: support storage data
|
||||
public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.components.impl.stores.DirectoryBasedStorage");
|
||||
|
||||
private final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
public class DirectoryBasedStorage extends StateStorageBase {
|
||||
private final File myDir;
|
||||
private final StateSplitter mySplitter;
|
||||
private final FileTypeManager myFileTypeManager;
|
||||
|
||||
private DirectoryStorageData myStorageData = null;
|
||||
private DirectoryStorageData myStorageData;
|
||||
|
||||
public DirectoryBasedStorage(@Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor,
|
||||
@NotNull String dir,
|
||||
@NotNull StateSplitter splitter,
|
||||
@NotNull Disposable parentDisposable,
|
||||
@Nullable final Listener listener) {
|
||||
myPathMacroSubstitutor = pathMacroSubstitutor;
|
||||
super(pathMacroSubstitutor);
|
||||
|
||||
myDir = new File(dir);
|
||||
mySplitter = splitter;
|
||||
Disposer.register(parentDisposable, this);
|
||||
|
||||
VirtualFileTracker virtualFileTracker = ServiceManager.getService(VirtualFileTracker.class);
|
||||
if (virtualFileTracker != null && listener != null) {
|
||||
final String path = myDir.getAbsolutePath();
|
||||
final String fileUrl = LocalFileSystem.PROTOCOL_PREFIX + path.replace(File.separatorChar, '/');
|
||||
virtualFileTracker.addTracker(fileUrl, new VirtualFileAdapter() {
|
||||
virtualFileTracker.addTracker(LocalFileSystem.PROTOCOL_PREFIX + myDir.getAbsolutePath().replace(File.separatorChar, '/'), new VirtualFileAdapter() {
|
||||
@Override
|
||||
public void contentsChanged(@NotNull final VirtualFileEvent event) {
|
||||
if (!StringUtilRt.endsWithIgnoreCase(event.getFile().getNameSequence(), ".xml")) return;
|
||||
assert listener != null;
|
||||
listener.storageFileChanged(event, DirectoryBasedStorage.this);
|
||||
public void contentsChanged(@NotNull VirtualFileEvent event) {
|
||||
notifyIfNeed(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileDeleted(@NotNull final VirtualFileEvent event) {
|
||||
if (!StringUtilRt.endsWithIgnoreCase(event.getFile().getNameSequence(), ".xml")) return;
|
||||
assert listener != null;
|
||||
listener.storageFileChanged(event, DirectoryBasedStorage.this);
|
||||
public void fileDeleted(@NotNull VirtualFileEvent event) {
|
||||
notifyIfNeed(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileCreated(@NotNull final VirtualFileEvent event) {
|
||||
if (!StringUtilRt.endsWithIgnoreCase(event.getFile().getNameSequence(), ".xml")) return;
|
||||
assert listener != null;
|
||||
listener.storageFileChanged(event, DirectoryBasedStorage.this);
|
||||
public void fileCreated(@NotNull VirtualFileEvent event) {
|
||||
notifyIfNeed(event);
|
||||
}
|
||||
}, false, this);
|
||||
|
||||
private void notifyIfNeed(@NotNull VirtualFileEvent event) {
|
||||
// storage directory will be removed if the only child was removed
|
||||
if (event.getFile().isDirectory() || DirectoryStorageData.isStorageFile(event.getFile())) {
|
||||
listener.storageFileChanged(event, DirectoryBasedStorage.this);
|
||||
}
|
||||
}
|
||||
}, false, parentDisposable);
|
||||
}
|
||||
|
||||
myFileTypeManager = FileTypeManager.getInstance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull Set<String> result) {
|
||||
boolean containsSelf = false;
|
||||
for (Pair<VirtualFile, StateStorage> pair : changedFiles) {
|
||||
if (pair.second == this && StringUtilRt.endsWithIgnoreCase(pair.first.getNameSequence(), ".xml")) {
|
||||
containsSelf = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!containsSelf) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> result) {
|
||||
// todo reload only changed file, compute diff
|
||||
myStorageData = loadState();
|
||||
result.addAll(myStorageData.getComponentNames());
|
||||
DirectoryStorageData oldData = myStorageData;
|
||||
DirectoryStorageData newData = loadState();
|
||||
myStorageData = newData;
|
||||
if (oldData == null) {
|
||||
result.addAll(newData.getComponentNames());
|
||||
}
|
||||
else {
|
||||
result.addAll(oldData.getComponentNames());
|
||||
result.addAll(newData.getComponentNames());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,7 +110,6 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
if (!myStorageData.containsComponent(componentName)) {
|
||||
return DefaultStateSerializer.deserializeState(new Element(StorageData.COMPONENT), stateClass, mergeInto);
|
||||
}
|
||||
|
||||
return myStorageData.getMergedState(componentName, stateClass, mySplitter, mergeInto);
|
||||
}
|
||||
|
||||
@@ -133,8 +120,9 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasState(@Nullable final Object component, @NotNull String componentName, final Class<?> aClass, final boolean reloadData) {
|
||||
if (!myDir.exists()) {
|
||||
public boolean hasState(@Nullable Object component, @NotNull String componentName, Class<?> aClass, boolean reloadData) {
|
||||
// dir could be deleted on VCS update: storage data is empty and dir doesn't exists - we must return true to reload component
|
||||
if (myStorageData == null && !myDir.exists()) {
|
||||
return false;
|
||||
}
|
||||
if (reloadData) {
|
||||
@@ -144,105 +132,24 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@Nullable
|
||||
public ExternalizationSession startExternalization() {
|
||||
if (myStorageData == null) {
|
||||
try {
|
||||
myStorageData = loadState();
|
||||
}
|
||||
catch (StateStorageException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
return new MyExternalizationSession(myStorageData.clone());
|
||||
return checkIsSavingDisabled() ? null : new MySaveSession(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SaveSession startSave(@NotNull ExternalizationSession externalizationSession) {
|
||||
return new MySaveSession(((MyExternalizationSession)externalizationSession).myStorageData, myPathMacroSubstitutor);
|
||||
return checkIsSavingDisabled() ? null : (MySaveSession)externalizationSession;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
private class MySaveSession implements SaveSession {
|
||||
private final DirectoryStorageData myStorageData;
|
||||
private final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
|
||||
private MySaveSession(@NotNull DirectoryStorageData storageData, @Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor) {
|
||||
myStorageData = storageData;
|
||||
myPathMacroSubstitutor = pathMacroSubstitutor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() throws StateStorageException {
|
||||
final Set<String> currentNames = new SmartHashSet<String>();
|
||||
File[] children = myDir.listFiles();
|
||||
if (children != null) {
|
||||
for (File child : children) {
|
||||
final String fileName = child.getName();
|
||||
if (!myFileTypeManager.isFileIgnored(fileName) && StringUtil.endsWithIgnoreCase(fileName, ".xml")) {
|
||||
currentNames.add(fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
myStorageData.process(new DirectoryStorageData.StorageDataProcessor() {
|
||||
@Override
|
||||
public void process(final String componentName, final File file, final Element element) {
|
||||
currentNames.remove(file.getName());
|
||||
|
||||
if (myPathMacroSubstitutor != null) {
|
||||
myPathMacroSubstitutor.collapsePaths(element);
|
||||
}
|
||||
|
||||
if (file.lastModified() <= myStorageData.getLastTimeStamp()) {
|
||||
StorageUtil.save(file, element, MySaveSession.this, false, LocalFileSystem.getInstance().findFileByIoFile(file));
|
||||
myStorageData.updateLastTimestamp(file);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (myDir.exists() && !currentNames.isEmpty()) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myDir.exists()) {
|
||||
for (String name : currentNames) {
|
||||
File child = new File(myDir, name);
|
||||
if (child.lastModified() > myStorageData.getLastTimeStamp()) {
|
||||
// do not touch new files during VC update (which aren't read yet)
|
||||
// now got an opposite problem: file is recreated if was removed by VC during update.
|
||||
return;
|
||||
}
|
||||
|
||||
final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(child);
|
||||
if (virtualFile != null) {
|
||||
try {
|
||||
LOG.debug("Removing configuration file: " + virtualFile.getPresentableUrl());
|
||||
virtualFile.delete(MySaveSession.this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
myStorageData.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private class MyExternalizationSession implements ExternalizationSession {
|
||||
private static class MySaveSession implements SaveSession, ExternalizationSession {
|
||||
private final DirectoryBasedStorage myStorage;
|
||||
private final DirectoryStorageData myStorageData;
|
||||
|
||||
private MyExternalizationSession(final DirectoryStorageData storageData) {
|
||||
myStorageData = storageData;
|
||||
private MySaveSession(@NotNull DirectoryBasedStorage storage) {
|
||||
myStorage = storage;
|
||||
myStorageData = storage.myStorageData == null ? storage.loadState() : storage.myStorageData.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -260,7 +167,7 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
if (element != null) {
|
||||
for (Pair<Element, String> pair : mySplitter.splitState(element)) {
|
||||
for (Pair<Element, String> pair : myStorage.mySplitter.splitState(element)) {
|
||||
Element e = pair.first;
|
||||
String name = pair.second;
|
||||
|
||||
@@ -268,9 +175,67 @@ public class DirectoryBasedStorage implements StateStorage, Disposable {
|
||||
statePart.setAttribute(StorageData.NAME, componentName);
|
||||
statePart.addContent(e.detach());
|
||||
|
||||
myStorageData.put(componentName, new File(myDir, name), statePart, false);
|
||||
myStorageData.put(componentName, new File(myStorage.myDir, name), statePart, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save() {
|
||||
final VirtualFile dir = LocalFileSystem.getInstance().findFileByIoFile(myStorage.myDir);
|
||||
final Set<String> existingFileNames = new SmartHashSet<String>();
|
||||
for (String componentName : myStorageData.getComponentNames()) {
|
||||
myStorageData.processComponent(componentName, new TObjectObjectProcedure<File, Element>() {
|
||||
@Override
|
||||
public boolean execute(File file, Element element) {
|
||||
String fileName = file.getName();
|
||||
existingFileNames.add(fileName);
|
||||
|
||||
if (myStorage.myPathMacroSubstitutor != null) {
|
||||
myStorage.myPathMacroSubstitutor.collapsePaths(element);
|
||||
}
|
||||
|
||||
if (file.lastModified() <= myStorageData.getLastTimeStamp()) {
|
||||
StorageUtil.save(file, element, MySaveSession.this, false, dir == null ? null : dir.findChild(fileName));
|
||||
myStorageData.updateLastTimestamp(file);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (dir != null && dir.exists()) {
|
||||
FileTypeManager fileTypeManager = FileTypeManager.getInstance();
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
for (VirtualFile file : dir.getChildren()) {
|
||||
String fileName = file.getName();
|
||||
if (fileTypeManager.isFileIgnored(fileName) || !DirectoryStorageData.isStorageFile(file) || existingFileNames.contains(fileName)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (file.getTimeStamp() > myStorageData.getLastTimeStamp()) {
|
||||
// do not touch new files during VC update (which aren't read yet)
|
||||
// now got an opposite problem: file is recreated if was removed by VC during update.
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
LOG.debug("Removing configuration file: " + file.getPresentableUrl());
|
||||
file.delete(this);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
}
|
||||
}
|
||||
|
||||
myStorage.myStorageData = myStorageData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -56,7 +56,7 @@ public class FileBasedStorage extends XmlElementStorage {
|
||||
@Nullable final Listener listener,
|
||||
@Nullable StreamProvider streamProvider,
|
||||
ComponentVersionProvider componentVersionProvider) {
|
||||
super(fileSpec, roamingType, pathMacroManager, parentDisposable, rootElementName, streamProvider, componentVersionProvider);
|
||||
super(fileSpec, roamingType, pathMacroManager, rootElementName, streamProvider, componentVersionProvider);
|
||||
|
||||
myFilePath = filePath;
|
||||
myFile = new File(filePath);
|
||||
@@ -82,12 +82,10 @@ public class FileBasedStorage extends XmlElementStorage {
|
||||
|
||||
@Override
|
||||
public void contentsChanged(@NotNull final VirtualFileEvent event) {
|
||||
if (!isDisposed()) {
|
||||
assert listener != null;
|
||||
listener.storageFileChanged(event, FileBasedStorage.this);
|
||||
}
|
||||
assert listener != null;
|
||||
listener.storageFileChanged(event, FileBasedStorage.this);
|
||||
}
|
||||
}, false, this);
|
||||
}, false, parentDisposable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@ import com.intellij.openapi.components.StateStorageException;
|
||||
import com.intellij.openapi.components.store.ComponentSaveSession;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -63,6 +64,6 @@ public interface IComponentStore {
|
||||
* list of not reloadable components (reload is not performed)
|
||||
*/
|
||||
@Nullable
|
||||
Collection<String> reload(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles);
|
||||
Collection<String> reload(@NotNull MultiMap<StateStorage, VirtualFile> changedStorages);
|
||||
}
|
||||
}
|
||||
|
||||
-1
@@ -324,7 +324,6 @@ public class StorageUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Contract")
|
||||
@Nullable
|
||||
public static Document loadDocument(@Nullable InputStream stream) {
|
||||
if (stream == null) {
|
||||
|
||||
+10
-45
@@ -15,11 +15,12 @@
|
||||
*/
|
||||
package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.components.store.StateStorageBase;
|
||||
import com.intellij.openapi.options.CurrentUserHolder;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -37,49 +38,38 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
protected static final Logger LOG = Logger.getInstance(XmlElementStorage.class);
|
||||
|
||||
public abstract class XmlElementStorage extends StateStorageBase {
|
||||
private static final String ATTR_NAME = "name";
|
||||
private static final String VERSION_FILE_SUFFIX = ".ver";
|
||||
|
||||
protected TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
@NotNull protected final String myRootElementName;
|
||||
protected StorageData myLoadedData;
|
||||
protected final StreamProvider myStreamProvider;
|
||||
protected final String myFileSpec;
|
||||
protected boolean myBlockSavingTheContent = false;
|
||||
private boolean mySavingDisabled = false;
|
||||
|
||||
private final ComponentVersionProvider myLocalVersionProvider;
|
||||
protected final RemoteComponentVersionProvider myRemoteVersionProvider;
|
||||
|
||||
protected final RoamingType myRoamingType;
|
||||
|
||||
private boolean myDisposed;
|
||||
|
||||
protected XmlElementStorage(@NotNull String fileSpec,
|
||||
@Nullable RoamingType roamingType,
|
||||
@Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor,
|
||||
@NotNull Disposable parentDisposable,
|
||||
@NotNull String rootElementName,
|
||||
@Nullable StreamProvider streamProvider,
|
||||
ComponentVersionProvider componentVersionProvider) {
|
||||
super(pathMacroSubstitutor);
|
||||
|
||||
myFileSpec = fileSpec;
|
||||
myRoamingType = roamingType == null ? RoamingType.PER_USER : roamingType;
|
||||
myPathMacroSubstitutor = pathMacroSubstitutor;
|
||||
myRootElementName = rootElementName;
|
||||
myStreamProvider = myRoamingType == RoamingType.DISABLED ? null : streamProvider;
|
||||
Disposer.register(parentDisposable, this);
|
||||
|
||||
myLocalVersionProvider = componentVersionProvider;
|
||||
myRemoteVersionProvider = streamProvider == null || !streamProvider.isVersioningRequired() ? null : new RemoteComponentVersionProvider();
|
||||
}
|
||||
|
||||
protected boolean isDisposed() {
|
||||
return myDisposed;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract Element loadLocalData();
|
||||
|
||||
@@ -170,19 +160,13 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
@Override
|
||||
@Nullable
|
||||
public final ExternalizationSession startExternalization() {
|
||||
if (LOG.isDebugEnabled() && myFileSpec.equals(StoragePathMacros.MODULE_FILE)) {
|
||||
LOG.debug("startExternalization: mySavingDisabled " + mySavingDisabled + " for " + toString());
|
||||
}
|
||||
return mySavingDisabled ? null : createSaveSession(getStorageData());
|
||||
return checkIsSavingDisabled() ? null : createSaveSession(getStorageData());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public SaveSession startSave(@NotNull ExternalizationSession externalizationSession) {
|
||||
if (mySavingDisabled) {
|
||||
if (LOG.isDebugEnabled() && myFileSpec.equals(StoragePathMacros.MODULE_FILE)) {
|
||||
LOG.debug("startSave: saving disabled for " + toString());
|
||||
}
|
||||
if (checkIsSavingDisabled()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
@@ -196,20 +180,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
|
||||
protected abstract XmlElementStorageSaveSession createSaveSession(@NotNull StorageData storageData);
|
||||
|
||||
public void disableSaving() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Saving disabled for " + toString());
|
||||
}
|
||||
mySavingDisabled = true;
|
||||
}
|
||||
|
||||
public void enableSaving() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Saving enabled for " + toString());
|
||||
}
|
||||
mySavingDisabled = false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final Element getElement(@NotNull StorageData data, boolean collapsePaths, @NotNull Map<String, Element> newLiveStates) {
|
||||
Element element = data.save(newLiveStates);
|
||||
@@ -230,7 +200,7 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull Set<String> result) {
|
||||
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> result) {
|
||||
StorageData oldData = myLoadedData;
|
||||
StorageData newData = getStorageData(true);
|
||||
if (oldData == null) {
|
||||
@@ -357,11 +327,6 @@ public abstract class XmlElementStorage implements StateStorage, Disposable {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
myDisposed = true;
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public void resetData() {
|
||||
myLoadedData = null;
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class StateStorageBase implements StateStorage {
|
||||
protected static final Logger LOG = Logger.getInstance(StateStorageBase.class);
|
||||
|
||||
private boolean mySavingDisabled = false;
|
||||
protected final TrackingPathMacroSubstitutor myPathMacroSubstitutor;
|
||||
|
||||
protected StateStorageBase(@Nullable TrackingPathMacroSubstitutor trackingPathMacroSubstitutor) {
|
||||
myPathMacroSubstitutor = trackingPathMacroSubstitutor;
|
||||
}
|
||||
|
||||
public final void disableSaving() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Disabled saving for " + toString());
|
||||
}
|
||||
mySavingDisabled = true;
|
||||
}
|
||||
|
||||
public final void enableSaving() {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Enabled saving " + toString());
|
||||
}
|
||||
mySavingDisabled = false;
|
||||
}
|
||||
|
||||
protected final boolean checkIsSavingDisabled() {
|
||||
if (mySavingDisabled && LOG.isDebugEnabled()) {
|
||||
LOG.debug("Saving disabled for " + toString());
|
||||
}
|
||||
return mySavingDisabled;
|
||||
}
|
||||
}
|
||||
+10
-11
@@ -31,6 +31,7 @@ import com.intellij.openapi.application.impl.ApplicationImpl;
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.components.impl.stores.*;
|
||||
import com.intellij.openapi.components.impl.stores.ComponentStoreImpl.ReloadComponentStoreStatus;
|
||||
import com.intellij.openapi.components.store.StateStorageBase;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.progress.*;
|
||||
@@ -198,7 +199,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
|
||||
|
||||
private void projectStorageFileChanged(@NotNull VirtualFileEvent event, @NotNull StateStorage storage, @Nullable Project project) {
|
||||
VirtualFile file = event.getFile();
|
||||
if (!StorageUtil.isChangedByStorageOrSaveSession(event) && !file.isDirectory() && !(event.getRequestor() instanceof ProjectManagerImpl)) {
|
||||
if (!StorageUtil.isChangedByStorageOrSaveSession(event) && !(event.getRequestor() instanceof ProjectManagerImpl)) {
|
||||
registerProjectToReload(project, file, storage);
|
||||
}
|
||||
}
|
||||
@@ -686,9 +687,7 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
|
||||
if (causes.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ReloadComponentStoreStatus status = ComponentStoreImpl.reloadStore(causes, ((ProjectEx)project).getStateStore());
|
||||
return status == ReloadComponentStoreStatus.RESTART_AGREED;
|
||||
return ComponentStoreImpl.reloadStore(causes, ((ProjectEx)project).getStateStore()) == ReloadComponentStoreStatus.RESTART_AGREED;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -751,20 +750,20 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
|
||||
}
|
||||
}
|
||||
|
||||
private void registerProjectToReload(@Nullable Project project, @NotNull VirtualFile cause, @NotNull StateStorage storage) {
|
||||
private void registerProjectToReload(@Nullable Project project, @NotNull VirtualFile file, @NotNull StateStorage storage) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("[RELOAD] Registering project to reload: " + cause, new Exception());
|
||||
LOG.debug("[RELOAD] Registering project to reload: " + file, new Exception());
|
||||
}
|
||||
|
||||
if (project == null) {
|
||||
myChangedApplicationFiles.add(Pair.create(cause, storage));
|
||||
myChangedApplicationFiles.add(Pair.create(file, storage));
|
||||
}
|
||||
else if (cause.exists()) {
|
||||
myChangedProjectFiles.putValue(project, Pair.create(cause, storage));
|
||||
else {
|
||||
myChangedProjectFiles.putValue(project, Pair.create(file, storage));
|
||||
}
|
||||
|
||||
if (storage instanceof XmlElementStorage) {
|
||||
((XmlElementStorage)storage).disableSaving();
|
||||
if (storage instanceof StateStorageBase) {
|
||||
((StateStorageBase)storage).disableSaving();
|
||||
}
|
||||
|
||||
if (isReloadUnblocked()) {
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ public class XmlElementStorageTest extends LightPlatformLangTestCase {
|
||||
private Element mySavedElement;
|
||||
|
||||
public MyXmlElementStorage(Element element, final Disposable parentDisposable) throws StateStorageException {
|
||||
super("", RoamingType.PER_USER, new MyPathMacroManager(), parentDisposable, "root", null, ComponentVersionProvider.EMPTY);
|
||||
super("", RoamingType.PER_USER, new MyPathMacroManager(), "root", null, ComponentVersionProvider.EMPTY);
|
||||
myElement = element;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.openapi.components;
|
||||
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileEvent;
|
||||
import com.intellij.util.messages.Topic;
|
||||
@@ -49,7 +48,7 @@ public interface StateStorage {
|
||||
/**
|
||||
* Get changed component names
|
||||
*/
|
||||
void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles, @NotNull Set<String> result);
|
||||
void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> result);
|
||||
|
||||
interface ExternalizationSession {
|
||||
void setState(@NotNull Object component, @NotNull String componentName, @NotNull Object state, @Nullable Storage storageSpec);
|
||||
|
||||
+29
-55
@@ -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.
|
||||
@@ -20,11 +20,10 @@ import com.intellij.openapi.components.StateSplitter;
|
||||
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Document;
|
||||
import gnu.trove.TObjectObjectProcedure;
|
||||
import org.jdom.Element;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -32,33 +31,40 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class DirectoryStorageData {
|
||||
private static final Logger LOG = Logger.getInstance(DirectoryStorageData.class);
|
||||
|
||||
private Map<String, Map<File, Element>> myStates = new THashMap<String, Map<File, Element>>();
|
||||
private Map<String, THashMap<File, Element>> myStates = new THashMap<String, THashMap<File, Element>>();
|
||||
private long myLastTimestamp = 0;
|
||||
private DirectoryStorageData myOriginalData;
|
||||
|
||||
@NotNull
|
||||
public Set<String> getComponentNames() {
|
||||
return myStates.keySet();
|
||||
}
|
||||
|
||||
public void loadFrom(final @Nullable VirtualFile dir, TrackingPathMacroSubstitutor pathMacroSubstitutor) {
|
||||
static boolean isStorageFile(@NotNull VirtualFile file) {
|
||||
// ignore system files like .DS_Store on Mac
|
||||
return StringUtilRt.endsWithIgnoreCase(file.getNameSequence(), ".xml");
|
||||
}
|
||||
|
||||
public void loadFrom(@Nullable VirtualFile dir, @Nullable TrackingPathMacroSubstitutor pathMacroSubstitutor) {
|
||||
if (dir == null || !dir.exists()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (VirtualFile file : dir.getChildren()) {
|
||||
if (!StringUtil.endsWithIgnoreCase(file.getName(), ".xml")) {
|
||||
//do not load system files like .DS_Store on Mac
|
||||
if (!isStorageFile(file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
final Document document = JDOMUtil.loadDocument(file.contentsToByteArray());
|
||||
final Element element = document.getRootElement();
|
||||
final Element element = JDOMUtil.loadDocument(file.contentsToByteArray()).detachRootElement();
|
||||
if (!element.getName().equals(StorageData.COMPONENT)) {
|
||||
LOG.error("Incorrect root tag name (" + element.getName() + ") in " + file.getPresentableUrl());
|
||||
continue;
|
||||
@@ -72,9 +78,7 @@ public class DirectoryStorageData {
|
||||
|
||||
if (pathMacroSubstitutor != null) {
|
||||
pathMacroSubstitutor.expandPaths(element);
|
||||
|
||||
final Set<String> unknownMacros = PathMacrosCollector.getMacroNames(element);
|
||||
pathMacroSubstitutor.addUnknownMacros(componentName, unknownMacros);
|
||||
pathMacroSubstitutor.addUnknownMacros(componentName, PathMacrosCollector.getMacroNames(element));
|
||||
}
|
||||
|
||||
put(componentName, new File(file.getPath()), element, true);
|
||||
@@ -88,10 +92,8 @@ public class DirectoryStorageData {
|
||||
}
|
||||
}
|
||||
|
||||
public void put(final String componentName, File file, final Element element, final boolean updateTimestamp) {
|
||||
LOG.assertTrue(componentName != null, String.format("Component name should not be null for file: %s", file == null ? "NULL!" : file.getPath()));
|
||||
|
||||
Map<File, Element> stateMap = myStates.get(componentName);
|
||||
public void put(@NotNull String componentName, @NotNull File file, @NotNull Element element, boolean updateTimestamp) {
|
||||
THashMap<File, Element> stateMap = myStates.get(componentName);
|
||||
if (stateMap == null) {
|
||||
stateMap = new THashMap<File, Element>();
|
||||
myStates.put(componentName, stateMap);
|
||||
@@ -103,7 +105,7 @@ public class DirectoryStorageData {
|
||||
}
|
||||
}
|
||||
|
||||
public void updateLastTimestamp(File file) {
|
||||
public void updateLastTimestamp(@NotNull File file) {
|
||||
myLastTimestamp = Math.max(myLastTimestamp, file.lastModified());
|
||||
if (myOriginalData != null) {
|
||||
myOriginalData.myLastTimestamp = myLastTimestamp;
|
||||
@@ -114,42 +116,17 @@ public class DirectoryStorageData {
|
||||
return myLastTimestamp;
|
||||
}
|
||||
|
||||
public Map<File, Long> getAllStorageFiles() {
|
||||
final Map<File, Long> allStorageFiles = new THashMap<File, Long>();
|
||||
process(new StorageDataProcessor() {
|
||||
@Override
|
||||
public void process(final String componentName, final File file, final Element element) {
|
||||
allStorageFiles.put(file, file.lastModified());
|
||||
}
|
||||
});
|
||||
|
||||
return allStorageFiles;
|
||||
}
|
||||
|
||||
public void processComponent(@NotNull final String componentName, @NotNull final PairConsumer<File, Element> consumer) {
|
||||
final Map<File, Element> map = myStates.get(componentName);
|
||||
void processComponent(@NotNull String componentName, @NotNull TObjectObjectProcedure<File, Element> consumer) {
|
||||
THashMap<File, Element> map = myStates.get(componentName);
|
||||
if (map != null) {
|
||||
for (File file : map.keySet()) {
|
||||
consumer.consume(file, map.get(file));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void process(@NotNull final StorageDataProcessor processor) {
|
||||
for (final String componentName : myStates.keySet()) {
|
||||
processComponent(componentName, new PairConsumer<File, Element>() {
|
||||
@Override
|
||||
public void consume(File file, Element element) {
|
||||
processor.process(componentName, file, element);
|
||||
}
|
||||
});
|
||||
map.forEachEntry(consumer);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DirectoryStorageData clone() {
|
||||
final DirectoryStorageData result = new DirectoryStorageData();
|
||||
result.myStates = new HashMap<String, Map<File, Element>>(myStates);
|
||||
result.myStates = new THashMap<String, THashMap<File, Element>>(myStates);
|
||||
result.myLastTimestamp = myLastTimestamp;
|
||||
result.myOriginalData = this;
|
||||
return result;
|
||||
@@ -171,14 +148,15 @@ public class DirectoryStorageData {
|
||||
@Nullable
|
||||
public <T> T getMergedState(String componentName, Class<T> stateClass, StateSplitter splitter, @Nullable T mergeInto) {
|
||||
final List<Element> subElements = new ArrayList<Element>();
|
||||
processComponent(componentName, new PairConsumer<File, Element>() {
|
||||
processComponent(componentName, new TObjectObjectProcedure<File, Element>() {
|
||||
@Override
|
||||
public void consume(File file, Element element) {
|
||||
public boolean execute(File file, Element element) {
|
||||
final List children = element.getChildren();
|
||||
assert children.size() == 1 : JDOMUtil.writeElement(element, File.separator);
|
||||
final Element subElement = (Element)children.get(0);
|
||||
Element subElement = (Element)children.get(0);
|
||||
subElement.detach();
|
||||
subElements.add(subElement);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -188,8 +166,4 @@ public class DirectoryStorageData {
|
||||
|
||||
return DefaultStateSerializer.deserializeState(state, stateClass, mergeInto);
|
||||
}
|
||||
|
||||
interface StorageDataProcessor {
|
||||
void process(String componentName, File file, Element element);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-9
@@ -26,7 +26,6 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.text.UniqueNameGenerator;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -78,22 +77,16 @@ public class ProjectLibraryTable extends LibraryTableBase {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public static class LibraryStateSplitter implements StateSplitter {
|
||||
|
||||
@Override
|
||||
public List<Pair<Element, String>> splitState(Element e) {
|
||||
final UniqueNameGenerator generator = new UniqueNameGenerator();
|
||||
|
||||
List<Pair<Element, String>> result = new ArrayList<Pair<Element, String>>();
|
||||
|
||||
final List list = e.getChildren();
|
||||
for (final Object o : list) {
|
||||
Element library = (Element)o;
|
||||
@NonNls final String name = generator.generateUniqueName(FileUtil.sanitizeFileName(library.getAttributeValue(LibraryImpl.LIBRARY_NAME_ATTR))) + ".xml";
|
||||
for (Element library : e.getChildren()) {
|
||||
String name = generator.generateUniqueName(FileUtil.sanitizeFileName(library.getAttributeValue(LibraryImpl.LIBRARY_NAME_ATTR))) + ".xml";
|
||||
result.add(Pair.create(library, name));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ 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;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -148,7 +148,7 @@ public class MockProjectStore implements IProjectStore {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Collection<String> reload(@NotNull Collection<Pair<VirtualFile, StateStorage>> changedFiles) {
|
||||
public Collection<String> reload(@NotNull MultiMap<StateStorage, VirtualFile> changedStorages) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user