/* * Copyright 2010-2015 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.kotlin.idea.framework.ui; import com.google.common.collect.Lists; import com.google.common.io.Closeables; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonParser; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.module.Module; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.DialogWrapper; import com.intellij.util.net.HttpConfigurable; import com.intellij.util.text.VersionComparatorUtil; import com.intellij.util.ui.AsyncProcessIcon; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.KotlinPluginUtil; import org.jetbrains.kotlin.idea.configuration.ConfigureKotlinInProjectUtilsKt; import org.jetbrains.kotlin.idea.configuration.KotlinProjectConfigurator; import org.jetbrains.kotlin.idea.configuration.RepositoryDescription; import org.jetbrains.kotlin.idea.versions.KotlinRuntimeLibraryUtilKt; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; public class ConfigureDialogWithModulesAndVersion extends DialogWrapper { private static final String VERSIONS_LIST_URL = "http://search.maven.org/solrsearch/select?q=g:%22org.jetbrains.kotlin%22+AND+a:%22kotlin-runtime%22&core=gav&rows=20&wt=json"; @NotNull private final String minimumVersion; private final ChooseModulePanel chooseModulePanel; private JPanel contentPane; private JPanel chooseModulesPanelPlace; private JComboBox kotlinVersionComboBox; private JPanel infoPanel; private final AsyncProcessIcon processIcon = new AsyncProcessIcon("loader"); public ConfigureDialogWithModulesAndVersion( @NotNull Project project, @NotNull KotlinProjectConfigurator configurator, @NotNull Collection<Module> excludeModules, @NotNull String minimumVersion ) { super(project); setTitle("Configure Kotlin with " + configurator.getPresentableText()); this.minimumVersion = minimumVersion; init(); ProgressManager.getInstance().run(new Task.Backgroundable(project, "Find Kotlin Maven plugin versions", false) { @Override public void run(@NotNull ProgressIndicator indicator) { loadKotlinVersions(); } }); kotlinVersionComboBox.addActionListener(new ActionListener() { @Override public void actionPerformed(@NotNull ActionEvent e) { updateComponents(); } }); kotlinVersionComboBox.addItem("loading..."); kotlinVersionComboBox.setEnabled(false); processIcon.resume(); infoPanel.add(processIcon, BorderLayout.CENTER); chooseModulePanel = new ChooseModulePanel(project, configurator, excludeModules); chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER); updateComponents(); } public List<Module> getModulesToConfigure() { return chooseModulePanel.getModulesToConfigure(); } public String getKotlinVersion() { return (String) kotlinVersionComboBox.getSelectedItem(); } @Nullable @Override protected JComponent createCenterPanel() { return contentPane; } private void loadKotlinVersions() { Collection<String> items; try { items = loadVersions(minimumVersion); hideLoader(); } catch (Throwable t) { items = Collections.singletonList("1.0.0"); showWarning(); } updateVersions(items); } private void hideLoader() { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { infoPanel.setVisible(false); infoPanel.updateUI(); } }, ModalityState.stateForComponent(infoPanel)); } private void showWarning() { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { infoPanel.remove(processIcon); infoPanel.add(new JLabel(UIUtil.getBalloonWarningIcon()), BorderLayout.CENTER); infoPanel.setToolTipText("Couldn't load versions list from search.maven.org"); infoPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); infoPanel.updateUI(); } }, ModalityState.stateForComponent(infoPanel)); } private void updateVersions(@NotNull final Collection<String> newItems) { ApplicationManager.getApplication().invokeLater(new Runnable() { @Override public void run() { kotlinVersionComboBox.removeAllItems(); kotlinVersionComboBox.setEnabled(true); for (String newItem : newItems) { kotlinVersionComboBox.addItem(newItem); } kotlinVersionComboBox.setSelectedIndex(0); } }, ModalityState.stateForComponent(kotlinVersionComboBox)); } @NotNull protected static Collection<String> loadVersions(String minimumVersion) throws Exception { List<String> versions = Lists.newArrayList(); String bundledRuntimeVersion = KotlinRuntimeLibraryUtilKt.bundledRuntimeVersion(); RepositoryDescription repositoryDescription = ConfigureKotlinInProjectUtilsKt.getRepositoryForVersion(bundledRuntimeVersion); if (repositoryDescription != null && repositoryDescription.getBintrayUrl() != null) { HttpURLConnection eapConnection = HttpConfigurable.getInstance().openHttpConnection(repositoryDescription.getBintrayUrl() + bundledRuntimeVersion); try { int timeout = (int) TimeUnit.SECONDS.toMillis(30); eapConnection.setConnectTimeout(timeout); eapConnection.setReadTimeout(timeout); if (eapConnection.getResponseCode() == 200) { versions.add(bundledRuntimeVersion); } } finally { eapConnection.disconnect(); } } HttpURLConnection urlConnection = HttpConfigurable.getInstance().openHttpConnection(VERSIONS_LIST_URL); try { int timeout = (int) TimeUnit.SECONDS.toMillis(30); urlConnection.setConnectTimeout(timeout); urlConnection.setReadTimeout(timeout); urlConnection.connect(); InputStreamReader streamReader = new InputStreamReader(urlConnection.getInputStream()); try { JsonElement rootElement = new JsonParser().parse(streamReader); JsonArray docsElements = rootElement.getAsJsonObject().get("response").getAsJsonObject().get("docs").getAsJsonArray(); for (JsonElement element : docsElements) { String versionNumber = element.getAsJsonObject().get("v").getAsString(); if (VersionComparatorUtil.compare(minimumVersion, versionNumber) <= 0) { versions.add(versionNumber); } } } finally { Closeables.closeQuietly(streamReader); } } finally { urlConnection.disconnect(); } Collections.sort(versions, VersionComparatorUtil.COMPARATOR.reversed()); // Handle the case when the new version has just been released and the Maven search index hasn't been updated yet if (!ConfigureKotlinInProjectUtilsKt.isEap(bundledRuntimeVersion) && !KotlinPluginUtil.isSnapshotVersion() && !bundledRuntimeVersion.contains("dev") && !versions.contains(bundledRuntimeVersion)) { versions.add(0, bundledRuntimeVersion); } return versions; } private void updateComponents() { setOKActionEnabled(kotlinVersionComboBox.isEnabled()); } }