- 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.
This commit is contained in:
Dmitry Trofimov
2014-03-10 19:38:15 +01:00
parent 52a92f2125
commit bbf4741efb
17 changed files with 349 additions and 23 deletions
@@ -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
}
@@ -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<PathMappingProvider> EP_NAME = ExtensionPointName.create("com.intellij.remote.pathMappingProvider");
public static List<PathMappingProvider> getSuitableMappingProviders(final RemoteSdkAdditionalData data) {
return Lists
.newArrayList(Iterables.filter(Arrays.asList(EP_NAME.getExtensions()), new Predicate<PathMappingProvider>() {
@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);
}
@@ -161,10 +161,4 @@ public class RemoteConnectionCredentialsWrapper {
throw unknownConnectionType();
}
}
public interface RemoteSdkConnectionAcceptor {
void ssh(RemoteCredentialsHolder cred);
void vagrant(VagrantBasedCredentialsHolder cred);
void deployment(WebDeploymentCredentialsHolder cred);
}
}
@@ -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;
}
}
}
@@ -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<RemoteCredentials> remoteCredentialsConsumer);
/**
* Used to select different credentials. This method should be fast.
* @return
*/
@NotNull
Object getConnectorKey();
}
@@ -40,4 +40,8 @@ public interface RemoteSdkAdditionalData<T extends RemoteSdkCredentials>
void setSshCredentials(@NotNull RemoteCredentialsHolder credentials);
void setDeploymentConnectionType(@NotNull WebDeploymentCredentialsHolder credentials);
CredentialsType getRemoteConnectionType();
void switchOnConnectionType(RemoteSdkConnectionAcceptor acceptor);
}
@@ -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);
}
@@ -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<SshConnectionProvider> EP_NAME = ExtensionPointName.create("RemoteRun.sshConnectionProvider");
@NotNull
Collection<? extends RemoteConnector> collectRemoteConnectors();
@Nullable
RemoteConnector getRemoteConnector(RemoteConnectionType type, @Nullable String id, Project project, Module module);
@Nullable
String getSettingCreationDescription();
@NotNull
@Nls
String getRadioButtonDescription();
@NotNull
RemoteConnectionType getTypeForConfigurable();
}
@@ -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<? extends RemoteConnector> collectRemoteConnectors() {
return collectVagrantConnections();
}
private static List<RemoteConnector> collectVagrantConnections() {
List<RemoteConnector> 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;
}
}
@@ -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<String, String> getVagrantInstanceParameters(@NotNull Project project);
public abstract Pair<String, RemoteCredentials> 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<? extends RemoteConnector> getVagrantInstancesConnectors(@NotNull Project project);
}
@@ -216,5 +216,7 @@
<extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
<extensionPoint name="tipAndTrick" beanClass="com.intellij.ide.util.TipAndTrickBean"/>
<extensionPoint qualifiedName="com.intellij.remote.pathMappingProvider" interface="com.intellij.remote.PathMappingProvider"/>
</extensionPoints>
</idea-plugin>
@@ -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<PythonC
private Process createRemoteConsoleProcess(PythonRemoteInterpreterManager manager, String[] command, Map<String, String> 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<PythonC
commandLine.getParametersList().set(3, "0");
myCommandLine = commandLine.getCommandLineString();
RemoteSshProcess remoteProcess =
manager.createRemoteProcess(getProject(), data, commandLine, true);
Pair<Integer, Integer> 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<Integer, Integer> 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;
}
@@ -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;
@@ -20,5 +20,5 @@ import com.intellij.remote.RemoteSdkAdditionalData;
/**
* @author traff
*/
public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData<PyRemoteSdkCredentials>, PySkeletonsPathAware {
public interface PyRemoteSdkAdditionalDataBase extends RemoteSdkAdditionalData<PyRemoteSdkCredentials>, PyRemoteSdkSkeletonsPathAware {
}
@@ -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{
}
@@ -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);
@@ -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) {