blob: 041e33cc5ac7e9c6edc4865210aef257eef9059c [file] [log] [blame]
/*
* 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 org.jetbrains.idea.svn.branchConfig;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.persistent.SmallMapSerializer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.EnumeratorStringDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: Irina.Chernushina
* Date: 8/24/11
* Time: 1:21 PM
*/
public class SvnLoadedBranchesStorage {
private final Object myLock;
private SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>> myState;
private final File myFile;
private final Project myProject;
public SvnLoadedBranchesStorage(final Project project) {
myProject = project;
final File vcsFile = new File(PathManager.getSystemPath(), "vcs");
File file = new File(vcsFile, "svn_branches");
file.mkdirs();
myFile = new File(file, project.getLocationHash());
myLock = new Object();
}
@Nullable
public Collection<SvnBranchItem> get(final String url) {
synchronized (myLock) {
if (myState == null) return null;
Map<String, Collection<SvnBranchItem>> map = myState.get("");
return map == null ? null : map.get(SvnBranchConfigurationNew.ensureEndSlash(url));
}
}
public void activate() {
synchronized (myLock) {
myState = new SmallMapSerializer<String, Map<String, Collection<SvnBranchItem>>>(myFile, new EnumeratorStringDescriptor(), createExternalizer());
}
}
public void deactivate() {
Map<String, Collection<SvnBranchItem>> branchLocationToBranchItemsMap = ContainerUtil.newHashMap();
SvnBranchConfigurationManager manager = SvnBranchConfigurationManager.getInstance(myProject);
Map<VirtualFile,SvnBranchConfigurationNew> mapCopy = manager.getSvnBranchConfigManager().getMapCopy();
for (Map.Entry<VirtualFile, SvnBranchConfigurationNew> entry : mapCopy.entrySet()) {
Map<String,InfoStorage<List<SvnBranchItem>>> branchMap = entry.getValue().getBranchMap();
for (Map.Entry<String, InfoStorage<List<SvnBranchItem>>> storageEntry : branchMap.entrySet()) {
branchLocationToBranchItemsMap.put(storageEntry.getKey(), storageEntry.getValue().getValue());
}
}
synchronized (myLock) {
// TODO: Possibly implement optimization - do not perform save if there are no changes in branch locations and branch items
// ensure myState.put() is called - so myState will treat itself as dirty and myState.force() will invoke real persisting
myState.put("", branchLocationToBranchItemsMap);
myState.force();
myState = null;
}
}
private DataExternalizer<Map<String, Collection<SvnBranchItem>>> createExternalizer() {
return new DataExternalizer<Map<String, Collection<SvnBranchItem>>>() {
@Override
public void save(@NotNull DataOutput out, Map<String, Collection<SvnBranchItem>> value) throws IOException {
out.writeInt(value.size());
ArrayList<String> keys = new ArrayList<String>(value.keySet());
Collections.sort(keys);
for (String key : keys) {
out.writeUTF(key);
List<SvnBranchItem> list = new ArrayList<SvnBranchItem>(value.get(key));
Collections.sort(list, SerializationComparator.getInstance());
out.writeInt(list.size());
for (SvnBranchItem item : list) {
out.writeUTF(item.getUrl());
out.writeLong(item.getCreationDateMillis());
out.writeLong(item.getRevision());
}
}
}
@Override
public Map<String, Collection<SvnBranchItem>> read(@NotNull DataInput in) throws IOException {
final HashMap<String, Collection<SvnBranchItem>> map = new HashMap<String, Collection<SvnBranchItem>>();
int mapSize = in.readInt();
for (int i = 0; i < mapSize; i++) {
final String key = in.readUTF();
final int size = in.readInt();
final ArrayList<SvnBranchItem> list = new ArrayList<SvnBranchItem>(size);
for (int j = 0; j < size; j++) {
String url = in.readUTF();
long creation = in.readLong();
long revision = in.readLong();
list.add(new SvnBranchItem(url, new Date(creation), revision));
}
map.put(key, list);
}
return map;
}
};
}
private static class SerializationComparator implements Comparator<SvnBranchItem> {
private final static SerializationComparator ourInstance = new SerializationComparator();
public static SerializationComparator getInstance() {
return ourInstance;
}
@Override
public int compare(SvnBranchItem o1, SvnBranchItem o2) {
return o1.getUrl().compareToIgnoreCase(o2.getUrl());
}
}
}