/*
* Copyright 2013-2017 consulo.io
*
* 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 consulo.externalStorage.storage;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.RoamingType;
import com.intellij.openapi.components.impl.stores.StateStorageManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.UnsyncByteArrayInputStream;
import com.intellij.util.io.UnsyncByteArrayOutputStream;
import consulo.externalStorage.ExternalStorageUtil;
import org.iq80.snappy.SnappyInputStream;
import org.iq80.snappy.SnappyOutputStream;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* @author VISTALL
* @since 12-Feb-17
*/
public class ExternalStorage {
private static final Logger LOGGER = Logger.getInstance(ExternalStorage.class);
private File myProxyDirectory;
private final ExternalStorageQueue myQueue = new ExternalStorageQueue();
public ExternalStorage() {
myProxyDirectory = new File(PathManager.getSystemPath(), "externalStorage");
}
@Nullable
public InputStream loadContent(String fileSpec, RoamingType roamingType, StateStorageManager stateStorageManager) throws IOException {
Ref<byte[]> ref = myQueue.getContent(fileSpec, roamingType);
if (ref != null) {
byte[] bytes = ref.get();
return bytes == null ? null : new SnappyInputStream(new UnsyncByteArrayInputStream(bytes));
}
InputStream stream = null;
int mod = -1;
File file = new File(myProxyDirectory, buildFileSpec(roamingType, fileSpec));
if (file.exists()) {
stream = new SnappyInputStream(new FileInputStream(file));
File modFile = ExternalStorageUtil.getModCountFile(file);
if (modFile.exists()) {
try {
mod = Integer.parseInt(FileUtil.loadFile(modFile));
}
catch (IOException ignored) {
}
}
}
myQueue.wantLoad(fileSpec, roamingType, mod, stateStorageManager);
return stream;
}
public void saveContent(@NotNull String fileSpec, @NotNull RoamingType roamingType, byte[] content, int size) throws IOException {
UnsyncByteArrayOutputStream out = new UnsyncByteArrayOutputStream(size);
try (SnappyOutputStream snappyOutputStream = new SnappyOutputStream(out)) {
snappyOutputStream.write(content, 0, size);
}
byte[] compressedContent = out.toByteArray();
myQueue.wantSave(myProxyDirectory, fileSpec, roamingType, compressedContent);
}
@NotNull
public Collection<String> listSubFiles(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
fileSpec = buildFileSpec(roamingType, fileSpec);
File proxy = new File(myProxyDirectory, fileSpec);
if (proxy.isDirectory() && proxy.isDirectory()) {
return Arrays.asList(proxy.list());
}
return Collections.emptyList();
}
public void delete(@NotNull String fileSpec, @NotNull RoamingType roamingType) {
fileSpec = buildFileSpec(roamingType, fileSpec);
File file = new File(myProxyDirectory, fileSpec);
file.delete();
}
@NotNull
public static String buildFileSpec(@NotNull RoamingType roamingType, @NotNull String fileSpec) {
switch (roamingType) {
case PER_PLATFORM:
return "$OS$/" + getOsPrefix() + "/" + fileSpec;
case PER_USER:
return "$GLOBAL$/" + fileSpec;
default:
throw new UnsupportedOperationException(roamingType.name());
}
}
@NotNull
private static String getOsPrefix() {
if (SystemInfo.isWindows) {
return "win";
}
else if (SystemInfo.isMac) {
return "mac";
}
else if (SystemInfo.isLinux) {
return "linux";
}
else if (SystemInfo.isFreeBSD) {
return "bsd";
}
else if (SystemInfo.isUnix) {
return "unix";
}
return "other";
}
}