| package com.intellij.remoteServer.impl.configuration; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.options.ConfigurationException; |
| import com.intellij.openapi.options.UnnamedConfigurable; |
| import com.intellij.openapi.progress.ProgressIndicator; |
| import com.intellij.openapi.progress.Task; |
| import com.intellij.openapi.ui.NamedConfigurable; |
| import com.intellij.openapi.util.Disposer; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.remoteServer.configuration.RemoteServer; |
| import com.intellij.remoteServer.configuration.ServerConfiguration; |
| import com.intellij.remoteServer.runtime.ServerConnection; |
| import com.intellij.remoteServer.runtime.ServerConnectionManager; |
| import com.intellij.remoteServer.runtime.ServerConnector; |
| import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance; |
| import com.intellij.remoteServer.util.CloudDataLoader; |
| import com.intellij.remoteServer.util.DelayedRunner; |
| import com.intellij.ui.components.JBLabel; |
| import com.intellij.util.concurrency.Semaphore; |
| import com.intellij.util.ui.UIUtil; |
| import com.intellij.util.xmlb.XmlSerializerUtil; |
| import org.jetbrains.annotations.Nls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import javax.swing.*; |
| import java.awt.*; |
| import java.util.concurrent.atomic.AtomicReference; |
| |
| /** |
| * @author nik |
| */ |
| public class RemoteServerConfigurable extends NamedConfigurable<RemoteServer<?>> { |
| |
| private static final Logger LOG = Logger.getInstance("#" + RemoteServerConfigurable.class.getName()); |
| |
| private static final String HELP_TOPIC_ID = "reference.settings.clouds"; |
| |
| |
| private final UnnamedConfigurable myConfigurable; |
| private final RemoteServer<?> myServer; |
| private String myServerName; |
| private boolean myNew; |
| private JPanel myMainPanel; |
| private JPanel mySettingsPanel; |
| private JBLabel myConnectionStatusLabel; |
| |
| private final DelayedRunner myRunner; |
| private ConnectionTester myConnectionTester; |
| |
| private final RemoteServer<?> myInnerServer; |
| private boolean myInnerApplied; |
| private boolean myUncheckedApply; |
| |
| private boolean myConnected; |
| |
| private CloudDataLoader myDataLoader = CloudDataLoader.NULL; |
| |
| public <C extends ServerConfiguration> RemoteServerConfigurable(RemoteServer<C> server, Runnable treeUpdater, boolean isNew) { |
| super(true, treeUpdater); |
| myServer = server; |
| myNew = isNew; |
| myServerName = myServer.getName(); |
| C configuration = server.getConfiguration(); |
| C innerConfiguration = XmlSerializerUtil.createCopy(configuration); |
| myInnerServer = new RemoteServerImpl<C>("<temp inner server>", server.getType(), innerConfiguration); |
| myInnerApplied = false; |
| myUncheckedApply = false; |
| |
| myConfigurable = server.getType().createConfigurable(innerConfiguration); |
| |
| myConnected = false; |
| myRunner = new DelayedRunner(myMainPanel) { |
| |
| @Override |
| protected boolean wasChanged() { |
| boolean modified = myConfigurable.isModified(); |
| boolean result = modified || myUncheckedApply; |
| if (result) { |
| myUncheckedApply = false; |
| |
| setConnectionStatus(false, false, ""); |
| myConnectionTester = null; |
| |
| if (modified) { |
| try { |
| myConfigurable.apply(); |
| myInnerApplied = true; |
| } |
| catch (ConfigurationException e) { |
| setConnectionStatus(true, false, e.getMessage()); |
| } |
| } |
| } |
| return result; |
| } |
| |
| @Override |
| protected void run() { |
| setConnectionStatus(false, false, "Connecting..."); |
| |
| myConnectionTester = new ConnectionTester(); |
| myConnectionTester.testConnection(); |
| } |
| }; |
| } |
| |
| private void setConnectionStatus(boolean error, boolean connected, String text) { |
| boolean changed = myConnected != connected; |
| myConnected = connected; |
| setConnectionStatusText(error, text); |
| if (changed) { |
| notifyDataLoader(); |
| } |
| } |
| |
| protected void setConnectionStatusText(boolean error, String text) { |
| myConnectionStatusLabel.setText(UIUtil.toHtml(text)); |
| myConnectionStatusLabel.setVisible(StringUtil.isNotEmpty(text)); |
| } |
| |
| public void setDataLoader(CloudDataLoader dataLoader) { |
| myDataLoader = dataLoader; |
| notifyDataLoader(); |
| } |
| |
| private void notifyDataLoader() { |
| if (myConnected) { |
| myDataLoader.loadCloudData(); |
| } |
| else { |
| myDataLoader.clearCloudData(); |
| } |
| } |
| |
| @Override |
| public RemoteServer<?> getEditableObject() { |
| return myServer; |
| } |
| |
| @Override |
| public String getBannerSlogan() { |
| return myServer.getName(); |
| } |
| |
| @Override |
| public JComponent createOptionsPanel() { |
| mySettingsPanel.add(BorderLayout.CENTER, myConfigurable.createComponent()); |
| return myMainPanel; |
| } |
| |
| @Nls |
| @Override |
| public String getDisplayName() { |
| return myServerName; |
| } |
| |
| @Nullable |
| @Override |
| public String getHelpTopic() { |
| return HELP_TOPIC_ID; |
| } |
| |
| @Override |
| public void setDisplayName(String name) { |
| myServerName = name; |
| } |
| |
| @Override |
| public boolean isModified() { |
| return myNew || myConfigurable.isModified() || myInnerApplied || !myServerName.equals(myServer.getName()); |
| } |
| |
| @Override |
| public void apply() throws ConfigurationException { |
| boolean uncheckedApply = myConfigurable.isModified(); |
| myConfigurable.apply(); |
| XmlSerializerUtil.copyBean(myInnerServer.getConfiguration(), myServer.getConfiguration()); |
| myNew = false; |
| myUncheckedApply = uncheckedApply; |
| myInnerApplied = false; |
| } |
| |
| @Override |
| public void reset() { |
| myConfigurable.reset(); |
| } |
| |
| @Override |
| public void disposeUIResources() { |
| myConfigurable.disposeUIResources(); |
| Disposer.dispose(myRunner); |
| } |
| |
| @Nullable |
| @Override |
| public Icon getIcon(boolean expanded) { |
| return myServer.getType().getIcon(); |
| } |
| |
| private class ConnectionTester { |
| |
| public void testConnection() { |
| final ServerConnection connection = ServerConnectionManager.getInstance().createTemporaryConnection(myInnerServer); |
| final AtomicReference<Boolean> connectedRef = new AtomicReference<Boolean>(null); |
| final Semaphore semaphore = new Semaphore(); |
| semaphore.down(); |
| connection.connectIfNeeded(new ServerConnector.ConnectionCallback() { |
| |
| @Override |
| public void connected(@NotNull ServerRuntimeInstance serverRuntimeInstance) { |
| connectedRef.set(true); |
| semaphore.up(); |
| connection.disconnect(); |
| } |
| |
| @Override |
| public void errorOccurred(@NotNull String errorMessage) { |
| connectedRef.set(false); |
| semaphore.up(); |
| } |
| }); |
| |
| new Task.Backgroundable(null, "Connecting...", true) { |
| @Override |
| public void run(@NotNull ProgressIndicator indicator) { |
| indicator.setIndeterminate(true); |
| while (!indicator.isCanceled()) { |
| if (semaphore.waitFor(500)) { |
| break; |
| } |
| } |
| final Boolean connected = connectedRef.get(); |
| if (connected == null) { |
| return; |
| } |
| UIUtil.invokeLaterIfNeeded(new Runnable() { |
| |
| @Override |
| public void run() { |
| if (myConnectionTester == ConnectionTester.this) { |
| setConnectionStatus(!connected, connected, connected ? "Connection successful" : "Cannot connect: " + connection.getStatusText()); |
| } |
| } |
| }); |
| } |
| }.queue(); |
| } |
| } |
| } |