From bbf4741efb3efc4ec6c54ba4829658639391b3e1 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Mon, 10 Mar 2014 19:38:15 +0100 Subject: [PATCH] - Removed dependency on remote-run in vagrant plugin (PY-12254). - New api for path mappings providers (old left for compatibility with RubyMine and PhpStorm) - Fix launching of Python console for remote interpreter. --- .../com/intellij/remote/CredentialsType.java | 23 ++++++ .../intellij/remote/PathMappingProvider.java | 40 +++++++++++ .../RemoteConnectionCredentialsWrapper.java | 6 -- .../intellij/remote/RemoteConnectionType.java | 17 +++++ .../com/intellij/remote/RemoteConnector.java | 28 ++++++++ .../remote/RemoteSdkAdditionalData.java | 4 ++ .../remote/RemoteSdkConnectionAcceptor.java | 25 +++++++ .../remote/SshConnectionProvider.java | 34 +++++++++ .../remote/VagrantSshConnectionProvider.java | 70 +++++++++++++++++++ .../com/intellij/remote/VagrantSupport.java | 57 +++++++++++++++ .../src/META-INF/PlatformExtensionPoints.xml | 2 + .../python/console/PydevConsoleRunner.java | 27 +++---- .../console/RunPythonConsoleAction.java | 4 +- .../remote/PyRemoteSdkAdditionalDataBase.java | 2 +- .../remote/PyRemoteSdkSkeletonsPathAware.java | 24 +++++++ .../PythonRemoteInterpreterManager.java | 4 +- .../python/run/PyRemoteProcessStarter.java | 5 +- 17 files changed, 349 insertions(+), 23 deletions(-) create mode 100644 platform/platform-impl/src/com/intellij/remote/CredentialsType.java create mode 100644 platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java create mode 100644 platform/platform-impl/src/com/intellij/remote/RemoteConnectionType.java create mode 100644 platform/platform-impl/src/com/intellij/remote/RemoteConnector.java create mode 100644 platform/platform-impl/src/com/intellij/remote/RemoteSdkConnectionAcceptor.java create mode 100644 platform/platform-impl/src/com/intellij/remote/SshConnectionProvider.java create mode 100644 platform/platform-impl/src/com/intellij/remote/VagrantSshConnectionProvider.java create mode 100644 platform/platform-impl/src/com/intellij/remote/VagrantSupport.java create mode 100644 python/src/com/jetbrains/python/remote/PyRemoteSdkSkeletonsPathAware.java diff --git a/platform/platform-impl/src/com/intellij/remote/CredentialsType.java b/platform/platform-impl/src/com/intellij/remote/CredentialsType.java new file mode 100644 index 000000000000..92d071c6c3fe --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/CredentialsType.java @@ -0,0 +1,23 @@ +/* + * 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 com.intellij.remote; + +/** + * @author traff + */ +public enum CredentialsType { + VAGRANT, WEB_DEPLOYMENT, SSH_HOST +} diff --git a/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java b/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java new file mode 100644 index 000000000000..2d4a76f1df1c --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/PathMappingProvider.java @@ -0,0 +1,40 @@ +package com.intellij.remote; + +import com.google.common.base.Predicate; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.projectRoots.Sdk; +import com.intellij.util.PathMappingSettings; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; + +/** + * @author traff + */ +public abstract class PathMappingProvider { + public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.remote.pathMappingProvider"); + + public static List getSuitableMappingProviders(final RemoteSdkAdditionalData data) { + return Lists + .newArrayList(Iterables.filter(Arrays.asList(EP_NAME.getExtensions()), new Predicate() { + @Override + public boolean apply(PathMappingProvider provider) { + return provider.accepts(data); + } + })); + } + + public abstract boolean accepts(@Nullable RemoteSdkAdditionalData data); + + @NotNull + public abstract PathMappingSettings getPathMappingSettings(@NotNull Project project, @NotNull RemoteSdkAdditionalData data); + + @Deprecated //Remove in IDEA 14 + @NotNull + public abstract PathMappingSettings getPathMapping(@NotNull Project project, @NotNull com.intellij.remotesdk.RemoteSdkAdditionalData data); +} diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java index a90f4a4df214..02322a23baf3 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionCredentialsWrapper.java @@ -161,10 +161,4 @@ public class RemoteConnectionCredentialsWrapper { throw unknownConnectionType(); } } - - public interface RemoteSdkConnectionAcceptor { - void ssh(RemoteCredentialsHolder cred); - void vagrant(VagrantBasedCredentialsHolder cred); - void deployment(WebDeploymentCredentialsHolder cred); - } } diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnectionType.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionType.java new file mode 100644 index 000000000000..823504cb2323 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnectionType.java @@ -0,0 +1,17 @@ +package com.intellij.remote; + +/** + * @author traff + */ +public enum RemoteConnectionType { + DEFAULT_SDK, DEPLOYMENT_SERVER, REMOTE_SDK, CURRENT_VAGRANT, NONE; + + public static RemoteConnectionType findByName(String name) { + try { + return valueOf(name); + } + catch (Exception e) { + return NONE; + } + } +} diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteConnector.java b/platform/platform-impl/src/com/intellij/remote/RemoteConnector.java new file mode 100644 index 000000000000..2083e82cf8b7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/RemoteConnector.java @@ -0,0 +1,28 @@ +package com.intellij.remote; + +import com.intellij.util.Consumer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author traff + */ +public interface RemoteConnector { + @Nullable + String getId(); + + @NotNull + String getName(); + + @Nullable + RemoteConnectionType getType(); + + void produceRemoteCredentials(Consumer remoteCredentialsConsumer); + + /** + * Used to select different credentials. This method should be fast. + * @return + */ + @NotNull + Object getConnectorKey(); +} diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java index 4cb6707f7577..1da39343b4c0 100644 --- a/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkAdditionalData.java @@ -40,4 +40,8 @@ public interface RemoteSdkAdditionalData void setSshCredentials(@NotNull RemoteCredentialsHolder credentials); void setDeploymentConnectionType(@NotNull WebDeploymentCredentialsHolder credentials); + + CredentialsType getRemoteConnectionType(); + + void switchOnConnectionType(RemoteSdkConnectionAcceptor acceptor); } diff --git a/platform/platform-impl/src/com/intellij/remote/RemoteSdkConnectionAcceptor.java b/platform/platform-impl/src/com/intellij/remote/RemoteSdkConnectionAcceptor.java new file mode 100644 index 000000000000..12e42526a5f7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/RemoteSdkConnectionAcceptor.java @@ -0,0 +1,25 @@ +/* + * 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 com.intellij.remote; + +/** +* @author traff +*/ +public interface RemoteSdkConnectionAcceptor { + void ssh(RemoteCredentialsHolder cred); + void vagrant(VagrantBasedCredentialsHolder cred); + void deployment(WebDeploymentCredentialsHolder cred); +} diff --git a/platform/platform-impl/src/com/intellij/remote/SshConnectionProvider.java b/platform/platform-impl/src/com/intellij/remote/SshConnectionProvider.java new file mode 100644 index 000000000000..3b3a9c44308c --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/SshConnectionProvider.java @@ -0,0 +1,34 @@ +package com.intellij.remote; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author lene + * Date: 05.07.13 + */ +public interface SshConnectionProvider { + ExtensionPointName EP_NAME = ExtensionPointName.create("RemoteRun.sshConnectionProvider"); + + @NotNull + Collection collectRemoteConnectors(); + + @Nullable + RemoteConnector getRemoteConnector(RemoteConnectionType type, @Nullable String id, Project project, Module module); + + @Nullable + String getSettingCreationDescription(); + + @NotNull + @Nls + String getRadioButtonDescription(); + + @NotNull + RemoteConnectionType getTypeForConfigurable(); +} diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSshConnectionProvider.java b/platform/platform-impl/src/com/intellij/remote/VagrantSshConnectionProvider.java new file mode 100644 index 000000000000..ff354be3fbb0 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/VagrantSshConnectionProvider.java @@ -0,0 +1,70 @@ +package com.intellij.remote; + +import com.google.common.collect.Lists; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.remote.RemoteConnectionType; +import com.intellij.remote.RemoteConnector; +import com.intellij.remote.SshConnectionProvider; +import org.jetbrains.annotations.Nls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; +import java.util.List; + +/** + * @author traff + */ +public class VagrantSshConnectionProvider implements SshConnectionProvider { + + @NotNull + @Override + public Collection collectRemoteConnectors() { + return collectVagrantConnections(); + } + + private static List collectVagrantConnections() { + List result = Lists.newArrayList(); + VagrantSupport vs = VagrantSupport.getInstance(); + if (vs != null) { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + result.addAll(vs.getVagrantInstancesConnectors(project)); + } + } + + return result; + } + + + @Nullable + @Override + public RemoteConnector getRemoteConnector(RemoteConnectionType type, @Nullable String id, Project project, Module module) { + for (RemoteConnector connector : collectRemoteConnectors()) { + if (connector.getType() == type && (connector.getId() != null && connector.getId().equals(id))) { + return connector; + } + } + return null; + } + + @Nullable + @Override + public String getSettingCreationDescription() { + return "add Vagrant"; + } + + @Nls + @NotNull + @Override + public String getRadioButtonDescription() { + return "Current Vagrant"; + } + + @NotNull + @Override + public RemoteConnectionType getTypeForConfigurable() { + return RemoteConnectionType.CURRENT_VAGRANT; + } +} diff --git a/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java new file mode 100644 index 000000000000..2ccf6b5f1ad7 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/remote/VagrantSupport.java @@ -0,0 +1,57 @@ +/* + * 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 com.intellij.remote; + +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Pair; +import com.intellij.util.ui.UIUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +/** + * @author traff + */ +public abstract class VagrantSupport { + public static VagrantSupport getInstance() { + return ServiceManager.getService(VagrantSupport.class); + } + + @Nullable + public abstract Pair getVagrantInstanceParameters(@NotNull Project project); + + public abstract Pair getVagrantSettings(Project data); + + public abstract RemoteCredentials getCredentials(@NotNull String folder); + + public static void showMissingVagrantSupportMessage(final @Nullable Project project) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + Messages.showErrorDialog(project, "Enable Vagrant Support plugin", + "Vagrant Support Disabled"); + } + }); + } + + public abstract void checkVagrantAndRunIfDown(String folder); + + public abstract Collection getVagrantInstancesConnectors(@NotNull Project project); +} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index eaff367e3eb1..efda8d658f58 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -216,5 +216,7 @@ + + diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java index 9daaf7f5dcfd..152078116339 100644 --- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java +++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java @@ -68,6 +68,7 @@ import com.jetbrains.python.console.completion.PydevConsoleElement; import com.jetbrains.python.console.parsing.PythonConsoleData; import com.jetbrains.python.console.pydev.ConsoleCommunication; import com.jetbrains.python.debugger.PySourcePosition; +import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.run.ProcessRunner; import com.jetbrains.python.run.PythonCommandLineState; @@ -307,7 +308,7 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory env) throws ExecutionException { - RemoteSdkCredentials data = (RemoteSdkCredentials)mySdk.getSdkAdditionalData(); + PyRemoteSdkAdditionalDataBase data = (PyRemoteSdkAdditionalDataBase)mySdk.getSdkAdditionalData(); assert data != null; GeneralCommandLine commandLine = new GeneralCommandLine(command); @@ -325,18 +326,20 @@ public class PydevConsoleRunner extends AbstractConsoleRunnerWithHistory remotePorts = getRemotePortsFromProcess(remoteProcess); - - remoteProcess.addLocalTunnel(myPorts[0], data.getHost(), remotePorts.first); - remoteProcess.addRemoteTunnel(remotePorts.second, "localhost", myPorts[1]); - - + try { + RemoteSdkCredentials remoteCredentials = data.getRemoteSdkCredentials(); + + RemoteSshProcess remoteProcess = + manager.createRemoteProcess(getProject(), remoteCredentials, commandLine, true); + + + Pair remotePorts = getRemotePortsFromProcess(remoteProcess); + + remoteProcess.addLocalTunnel(myPorts[0], remoteCredentials.getHost(), remotePorts.first); + remoteProcess.addRemoteTunnel(remotePorts.second, "localhost", myPorts[1]); + + myPydevConsoleCommunication = new PydevConsoleCommunication(getProject(), myPorts[0], remoteProcess, myPorts[1]); return remoteProcess; } diff --git a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java index 728056cca301..d01159e759fc 100644 --- a/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java +++ b/python/src/com/jetbrains/python/console/RunPythonConsoleAction.java @@ -35,7 +35,9 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.PathMappingSettings; import com.jetbrains.python.buildout.BuildoutFacet; +import com.jetbrains.python.remote.PyRemoteSdkAdditionalDataBase; import com.jetbrains.python.remote.PyRemoteSdkCredentials; +import com.jetbrains.python.remote.PyRemoteSdkSkeletonsPathAware; import com.jetbrains.python.remote.PythonRemoteInterpreterManager; import com.jetbrains.python.run.PythonCommandLineState; import com.jetbrains.python.sdk.PySdkUtil; @@ -153,7 +155,7 @@ public class RunPythonConsoleAction extends AnAction implements DumbAware { PythonRemoteInterpreterManager instance = PythonRemoteInterpreterManager.getInstance(); if (instance != null) { mappingSettings = - instance.setupMappings(project, (PyRemoteSdkCredentials)sdk.getSdkAdditionalData(), null); + instance.setupMappings(project, (PyRemoteSdkAdditionalDataBase)sdk.getSdkAdditionalData(), null); } } return mappingSettings; diff --git a/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java b/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java index 66cceb192a04..e1514ba26dae 100644 --- a/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java +++ b/python/src/com/jetbrains/python/remote/PyRemoteSdkAdditionalDataBase.java @@ -20,5 +20,5 @@ import com.intellij.remote.RemoteSdkAdditionalData; /** * @author traff */ -public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData, PySkeletonsPathAware { +public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData, PyRemoteSdkSkeletonsPathAware { } diff --git a/python/src/com/jetbrains/python/remote/PyRemoteSdkSkeletonsPathAware.java b/python/src/com/jetbrains/python/remote/PyRemoteSdkSkeletonsPathAware.java new file mode 100644 index 000000000000..f49fed538296 --- /dev/null +++ b/python/src/com/jetbrains/python/remote/PyRemoteSdkSkeletonsPathAware.java @@ -0,0 +1,24 @@ +/* + * 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 com.jetbrains.python.remote; + +import com.intellij.remote.RemoteSdkProperties; + +/** + * @author traff + */ +public interface PyRemoteSdkSkeletonsPathAware extends PySkeletonsPathAware, RemoteSdkProperties{ +} diff --git a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java index 4276ed8cafe5..b080792e2a96 100644 --- a/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java +++ b/python/src/com/jetbrains/python/remote/PythonRemoteInterpreterManager.java @@ -126,7 +126,7 @@ public abstract class PythonRemoteInterpreterManager { return FileUtil.toSystemIndependentName(path).replace('/', separator); } - public static void addHelpersMapping(@NotNull RemoteSdkCredentials data, @Nullable PathMappingSettings newMappingSettings) { + public static void addHelpersMapping(@NotNull RemoteSdkProperties data, @Nullable PathMappingSettings newMappingSettings) { if (newMappingSettings == null) { newMappingSettings = new PathMappingSettings(); } @@ -134,7 +134,7 @@ public abstract class PythonRemoteInterpreterManager { } public abstract PathMappingSettings setupMappings(@Nullable Project project, - @NotNull PyRemoteSdkCredentials data, + @NotNull PyRemoteSdkAdditionalDataBase data, @Nullable PathMappingSettings mappingSettings); public abstract SdkAdditionalData loadRemoteSdkData(Sdk sdk, Element additional); diff --git a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java index 673b87dfd53d..d5ba031d6d67 100644 --- a/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java +++ b/python/src/com/jetbrains/python/run/PyRemoteProcessStarter.java @@ -70,8 +70,11 @@ public class PyRemoteProcessStarter { SdkAdditionalData data = sdk.getSdkAdditionalData(); assert data instanceof PyRemoteSdkAdditionalDataBase; + PyRemoteSdkAdditionalDataBase pyRemoteSdkAdditionalDataBase = (PyRemoteSdkAdditionalDataBase)data; try { - return manager.startRemoteProcess(project, ((PyRemoteSdkAdditionalDataBase)data).getRemoteSdkCredentials(), commandLine, + settings = manager.setupMappings(project, pyRemoteSdkAdditionalDataBase, settings); + + return manager.startRemoteProcess(project, pyRemoteSdkAdditionalDataBase.getRemoteSdkCredentials(), commandLine, settings); } catch (InterruptedException e) {