blob: 63bd5586d192de256f52ed7b5c95b0c1aa7634eb [file] [log] [blame]
package com.intellij.remoteServer.impl.runtime.clientLibrary;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.PersistentStateComponent;
import com.intellij.openapi.components.State;
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.remoteServer.runtime.clientLibrary.ClientLibraryDescription;
import com.intellij.remoteServer.runtime.clientLibrary.ClientLibraryManager;
import com.intellij.util.EventDispatcher;
import com.intellij.util.download.*;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
/**
* @author michael.golubev
*/
@State(
name = "RemoteServerClientLibraries",
storages = {
@Storage(file = StoragePathMacros.APP_CONFIG + "/remote-server-client-libraries.xml")
}
)
public class ClientLibraryManagerImpl extends ClientLibraryManager implements PersistentStateComponent<ClientLibraryManagerImpl.State> {
private static final Logger LOG = Logger.getInstance(ClientLibraryManagerImpl.class);
private Map<String, List<File>> myFiles = new LinkedHashMap<String, List<File>>();
private EventDispatcher<CloudClientLibraryManagerListener> myEventDispatcher
= EventDispatcher.create(CloudClientLibraryManagerListener.class);
@Override
public void addListener(@NotNull CloudClientLibraryManagerListener listener, @NotNull Disposable disposable) {
myEventDispatcher.addListener(listener, disposable);
}
public State getState() {
State result = new State();
for (Map.Entry<String, List<File>> entry : myFiles.entrySet()) {
DownloadedLibraryState libraryState = new DownloadedLibraryState();
libraryState.myId = entry.getKey();
for (File file : entry.getValue()) {
libraryState.myPaths.add(FileUtil.toSystemIndependentName(file.getAbsolutePath()));
}
result.myLibraries.add(libraryState);
}
return result;
}
@Override
public void loadState(State state) {
myFiles = new HashMap<String, List<File>>();
for (DownloadedLibraryState libraryState : state.myLibraries) {
List<File> files = new ArrayList<File>();
for (String path : libraryState.myPaths) {
files.add(new File(path));
}
myFiles.put(libraryState.myId, files);
}
}
@Override
public boolean isDownloaded(@NotNull ClientLibraryDescription description) {
return !getExistentFiles(description).isEmpty();
}
@NotNull
private List<File> getExistentFiles(ClientLibraryDescription description) {
List<File> files = myFiles.get(description.getId());
if (files == null) {
return Collections.emptyList();
}
List<File> existentFiles = new ArrayList<File>();
for (File file : files) {
if (file.exists()) {
existentFiles.add(file);
}
}
return existentFiles;
}
@Override
public void checkConfiguration(@NotNull final ClientLibraryDescription description, final @Nullable Project project,
final @Nullable JComponent component) throws RuntimeConfigurationError {
if (!isDownloaded(description)) {
throw new RuntimeConfigurationError("Client libraries were not downloaded", new Runnable() {
@Override
public void run() {
download(description, project, component);
}
});
}
}
private static File getStoreDirectory(ClientLibraryDescription description) {
return new File(PathManager.getSystemPath(), "remote-server-libraries/" + description.getId());
}
@NotNull
@Override
public List<File> getLibraries(@NotNull ClientLibraryDescription description) {
File[] files = getStoreDirectory(description).listFiles();
return files == null ? Collections.<File>emptyList() : Arrays.asList(files);
}
@Override
public void download(@NotNull final ClientLibraryDescription libraryDescription, @Nullable Project project, @Nullable JComponent component) {
final Ref<IOException> exc = Ref.create(null);
ProgressManager.getInstance().runProcessWithProgressSynchronously(
new Runnable() {
@Override
public void run() {
try {
download(libraryDescription);
}
catch (IOException e) {
exc.set(e);
}
}
}, "Downloading Client Libraries", false, project, component);
if (exc.isNull()) {
myEventDispatcher.getMulticaster().downloaded();
}
else {
LOG.info(exc.get());
}
}
@NotNull
@Override
public List<File> download(@NotNull final ClientLibraryDescription libraryDescription) throws IOException {
List<File> existentFiles = getExistentFiles(libraryDescription);
if (!existentFiles.isEmpty()) {
return existentFiles;
}
final DownloadableFileService downloadService = DownloadableFileService.getInstance();
URL versionsUrl = libraryDescription.getDescriptionUrl();
final DownloadableFileSetVersions<DownloadableFileSetDescription> versions = downloadService.createFileSetVersions(null, versionsUrl);
List<DownloadableFileSetDescription> descriptions = versions.fetchVersions();
if (descriptions.isEmpty()) {
throw new IOException("No client library versions loaded");
}
FileDownloader downloader = downloadService.createDownloader(descriptions.get(0));
List<Pair<File, DownloadableFileDescription>> downloaded = downloader.download(getStoreDirectory(libraryDescription));
List<File> files = myFiles.get(libraryDescription.getId());
if (files == null) {
files = new ArrayList<File>();
myFiles.put(libraryDescription.getId(), files);
}
for (Pair<File, DownloadableFileDescription> pair : downloaded) {
files.add(pair.getFirst());
}
myEventDispatcher.getMulticaster().downloaded();
return files;
}
@Tag("client-library")
public static class DownloadedLibraryState {
@Attribute("id")
public String myId;
@Property(surroundWithTag = false)
@AbstractCollection(surroundWithTag = false, elementTag = "file", elementValueAttribute = "path")
public List<String> myPaths = new ArrayList<String>();
}
public static class State {
@Property(surroundWithTag = false)
@AbstractCollection(surroundWithTag = false)
public List<DownloadedLibraryState> myLibraries = new ArrayList<DownloadedLibraryState>();
}
}