IDEA-146319 Move PyCharm implementation of process list retrieval to the platform

Moved and refactored a bit PyCharm implementation of process list retrieval
This commit is contained in:
Alexey Ushakov
2015-11-24 19:31:42 +03:00
parent 6555e34dc0
commit 114e0164df
10 changed files with 179 additions and 84 deletions
@@ -1,3 +1,19 @@
/*
* Copyright 2000-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.
*/
// From: http://www.halley.cc/code/?java/CSVReader.java
/**
@@ -16,7 +32,7 @@
limitations under the License.
*/
package com.jetbrains.python.internal.win32;
package com.intellij.execution.process;
import java.io.BufferedReader;
import java.io.IOException;
@@ -1,3 +1,19 @@
/*
* Copyright 2000-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.
*/
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
@@ -8,12 +24,12 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package com.jetbrains.python.internal;
package com.intellij.execution.process;
/**
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface IProcessList {
PyProcessInfo[] getProcessList();
ProcessInfo[] getProcessList();
}
@@ -9,24 +9,39 @@
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package com.jetbrains.python.internal;
/*
* Copyright 2000-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 com.intellij.execution.process;
import com.google.common.base.Joiner;
/**
* @author traff
*/
public class PyProcessInfo {
public class ProcessInfo {
private final int myPid;
private final String myCommand;
private final String myArgs;
public PyProcessInfo(String pidString, String name) {
public ProcessInfo(String pidString, String name) {
this(Integer.parseInt(pidString), name);
}
public PyProcessInfo(int pid, String name) {
public ProcessInfo(int pid, String name) {
myPid = pid;
String[] args = name.split(" ");
myCommand = args.length > 0 ? args[0] : "";
@@ -1,3 +1,19 @@
/*
* Copyright 2000-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.
*/
/*******************************************************************************
* Copyright (c) 2000, 2010 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
@@ -8,24 +24,19 @@
* Contributors:
* QNX Software Systems - Initial API and implementation
*******************************************************************************/
package com.jetbrains.python.internal.linux;
package com.intellij.execution.process;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import com.intellij.openapi.util.io.FileUtil;
import com.jetbrains.python.internal.ProcessUtils;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.IProcessList;
import com.jetbrains.python.internal.PyProcessInfo;
/**
* Use through PlatformUtils.
*/
public class ProcessListLinux implements IProcessList {
PyProcessInfo[] empty = new PyProcessInfo[0];
ProcessInfo[] empty = new ProcessInfo[0];
public ProcessListLinux() {
}
@@ -35,7 +46,7 @@ public class ProcessListLinux implements IProcessList {
*
* @see IProcessList#getProcessList
*/
public PyProcessInfo[] getProcessList() {
public ProcessInfo[] getProcessList() {
File proc = new File("/proc"); //$NON-NLS-1$
File[] pidFiles = null;
@@ -58,9 +69,9 @@ public class ProcessListLinux implements IProcessList {
catch (SecurityException e) {
}
PyProcessInfo[] processInfo = empty;
ProcessInfo[] processInfo = empty;
if (pidFiles != null) {
processInfo = new PyProcessInfo[pidFiles.length];
processInfo = new ProcessInfo[pidFiles.length];
for (int i = 0; i < pidFiles.length; i++) {
File cmdLine = new File(pidFiles[i], "cmdline"); //$NON-NLS-1$
String name;
@@ -73,7 +84,7 @@ public class ProcessListLinux implements IProcessList {
if (name.length() == 0) {
name = "Unknown"; //$NON-NLS-1$
}
processInfo[i] = new PyProcessInfo(pidFiles[i].getName(), name);
processInfo[i] = new ProcessInfo(pidFiles[i].getName(), name);
}
}
else {
@@ -1,3 +1,19 @@
/*
* Copyright 2000-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.
*/
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
@@ -8,24 +24,20 @@
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package com.jetbrains.python.internal.macos;
package com.intellij.execution.process;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;
import com.google.common.collect.Lists;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.IProcessList;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.ProcessUtils;
/**
* Use through PlatformUtils.
*/
public class ProcessListMac implements IProcessList {
PyProcessInfo[] empty = new PyProcessInfo[0];
ProcessInfo[] empty = new ProcessInfo[0];
public ProcessListMac() {
}
@@ -34,7 +46,7 @@ public class ProcessListMac implements IProcessList {
* Insert the method's description here.
* @see IProcessList#getProcessList
*/
public PyProcessInfo[] getProcessList() {
public ProcessInfo[] getProcessList() {
Process ps;
BufferedReader psOutput;
String[] args = { "/bin/ps", "-a", "-x", "-o", "pid,command" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
@@ -43,11 +55,11 @@ public class ProcessListMac implements IProcessList {
ps = ProcessUtils.createProcess(args, null, null);
psOutput = new BufferedReader(new InputStreamReader(ps.getInputStream()));
} catch (Exception e) {
return new PyProcessInfo[0];
return new ProcessInfo[0];
}
//Read the output and parse it into an array list
List<PyProcessInfo> procInfo = Lists.newArrayList();
List<ProcessInfo> procInfo = Lists.newArrayList();
try {
String lastline;
@@ -61,7 +73,7 @@ public class ProcessListMac implements IProcessList {
try {
int pid = Integer.parseInt(pidString);
String arg = lastline.substring(index + 1);
procInfo.add(new PyProcessInfo(pid, arg));
procInfo.add(new ProcessInfo(pid, arg));
} catch (NumberFormatException e) {
}
}
@@ -72,6 +84,6 @@ public class ProcessListMac implements IProcessList {
}
ps.destroy();
return procInfo.toArray(new PyProcessInfo[procInfo.size()]);
return procInfo.toArray(new ProcessInfo[procInfo.size()]);
}
}
@@ -1,3 +1,18 @@
/*
* Copyright 2000-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.
*/
/*******************************************************************************
* Copyright (c) 2014 Brainwy Software Ltda.
* All rights reserved. This program and the accompanying materials
@@ -8,7 +23,7 @@
* Contributors:
* Fabio Zadrozny
*******************************************************************************/
package com.jetbrains.python.internal.win32;
package com.intellij.execution.process;
import java.io.BufferedReader;
import java.io.IOException;
@@ -19,10 +34,6 @@ import java.util.List;
import com.google.common.base.Joiner;
import com.intellij.openapi.diagnostic.Logger;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.IProcessList;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.ProcessUtils;
/*
* This implementation uses the tasklist.exe from windows (must be on the path).
@@ -38,7 +49,7 @@ public class ProcessListWin32 implements IProcessList {
myHelpersRoot = helpersRoot;
}
public PyProcessInfo[] getProcessList() {
public ProcessInfo[] getProcessList() {
try {
return createFromWMIC();
@@ -49,7 +60,7 @@ public class ProcessListWin32 implements IProcessList {
Process p = null;
InputStream in = null;
PyProcessInfo[] procInfos = new PyProcessInfo[0];
ProcessInfo[] procInfos = new ProcessInfo[0];
try {
@@ -80,11 +91,11 @@ public class ProcessListWin32 implements IProcessList {
return procInfos;
}
private PyProcessInfo[] createFromWMIC() throws Exception {
private ProcessInfo[] createFromWMIC() throws Exception {
Process p = ProcessUtils.createProcess(new String[]{"wmic.exe", "path", "win32_process", "get",
"Caption,Processid,Commandline"}, null,
null);
List<PyProcessInfo> lst = new ArrayList<PyProcessInfo>();
List<ProcessInfo> lst = new ArrayList<ProcessInfo>();
InputStream in = p.getInputStream();
InputStreamReader reader = new InputStreamReader(in);
try {
@@ -112,12 +123,12 @@ public class ProcessListWin32 implements IProcessList {
String name = line.substring(0, commandLineI).trim();
String commandLine = line.substring(commandLineI, processIdI).trim();
String processId = line.substring(processIdI, line.length()).trim();
lst.add(new PyProcessInfo(Integer.parseInt(processId), name + " " + commandLine));
lst.add(new ProcessInfo(Integer.parseInt(processId), name + " " + commandLine));
}
if (lst.size() == 0) {
throw new AssertionError("Error: no processes found");
}
return lst.toArray(new PyProcessInfo[0]);
return lst.toArray(new ProcessInfo[0]);
}
catch (Exception e) {
LOG.error(e);
@@ -128,10 +139,10 @@ public class ProcessListWin32 implements IProcessList {
}
}
public PyProcessInfo[] parseListTasks(InputStreamReader reader) {
public ProcessInfo[] parseListTasks(InputStreamReader reader) {
BufferedReader br = new BufferedReader(reader);
CSVReader csvReader = new CSVReader(br);
List<PyProcessInfo> processList = new ArrayList();
List<ProcessInfo> processList = new ArrayList();
String[] next;
do {
try {
@@ -139,7 +150,7 @@ public class ProcessListWin32 implements IProcessList {
if (next != null) {
int pid = Integer.parseInt(next[1]);
String name = Joiner.on(" - ").join(next[0], next[next.length - 1]);
processList.add(new PyProcessInfo(pid, name));
processList.add(new ProcessInfo(pid, name));
}
}
catch (IOException e) {
@@ -148,6 +159,6 @@ public class ProcessListWin32 implements IProcessList {
}
while (next != null);
return processList.toArray(new PyProcessInfo[processList.size()]);
return processList.toArray(new ProcessInfo[processList.size()]);
}
}
@@ -1,21 +1,22 @@
/*******************************************************************************
* Copyright (c) 2000, 2014 QNX Software Systems and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Contributors:
* QNX Software Systems - Initial API and implementation
* Martin Oberhuber (Wind River) - [303083] Split out the Spawner
*******************************************************************************/
package com.jetbrains.python.internal.win32;
* 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.execution.process;
import com.google.common.collect.Lists;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.IProcessList;
import com.jetbrains.python.internal.PyProcessInfo;
import com.jetbrains.python.internal.ProcessUtils;
import java.io.*;
import java.util.List;
@@ -27,7 +28,7 @@ import java.util.List;
*/
public class ProcessListWin32Internal implements IProcessList {
private PyProcessInfo[] NOPROCESS = new PyProcessInfo[0];
private ProcessInfo[] NOPROCESS = new ProcessInfo[0];
private String myHelpersRoot;
public ProcessListWin32Internal(String helpersRoot) {
@@ -35,11 +36,11 @@ public class ProcessListWin32Internal implements IProcessList {
myHelpersRoot = helpersRoot;
}
public PyProcessInfo[] getProcessList() {
public ProcessInfo[] getProcessList() {
Process p = null;
String command = null;
InputStream in = null;
PyProcessInfo[] procInfos = NOPROCESS;
ProcessInfo[] procInfos = NOPROCESS;
try {
File file = new File(myHelpersRoot, "process/listtasks.exe");
@@ -74,9 +75,9 @@ public class ProcessListWin32Internal implements IProcessList {
return procInfos;
}
public PyProcessInfo[] parseListTasks(InputStreamReader reader) {
public ProcessInfo[] parseListTasks(InputStreamReader reader) {
BufferedReader br = new BufferedReader(reader);
List<PyProcessInfo> processList = Lists.newArrayList();
List<ProcessInfo> processList = Lists.newArrayList();
try {
String line;
while ((line = br.readLine()) != null) {
@@ -87,7 +88,7 @@ public class ProcessListWin32Internal implements IProcessList {
if (proc.length() > 0 && name.length() > 0) {
try {
int pid = Integer.parseInt(proc);
processList.add(new PyProcessInfo(pid, name));
processList.add(new ProcessInfo(pid, name));
}
catch (NumberFormatException e) {
}
@@ -97,6 +98,6 @@ public class ProcessListWin32Internal implements IProcessList {
}
catch (IOException e) {
}
return processList.toArray(new PyProcessInfo[processList.size()]);
return processList.toArray(new ProcessInfo[processList.size()]);
}
}
@@ -1,3 +1,19 @@
/*
* Copyright 2000-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.
*/
/******************************************************************************
* Copyright (C) 2013 Fabio Zadrozny
*
@@ -9,14 +25,10 @@
* Contributors:
* Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation
******************************************************************************/
package com.jetbrains.python.internal;
package com.intellij.execution.process;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.jetbrains.python.console.pydev.FastStringBuffer;
import com.jetbrains.python.internal.linux.ProcessListLinux;
import com.jetbrains.python.internal.macos.ProcessListMac;
import com.jetbrains.python.internal.win32.ProcessListWin32;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
@@ -65,8 +77,8 @@ public class ProcessUtils {
return new IProcessList() {
@Override
public PyProcessInfo[] getProcessList() {
return new PyProcessInfo[0];
public ProcessInfo[] getProcessList() {
return new ProcessInfo[0];
}
};
}
@@ -94,13 +106,13 @@ public class ProcessUtils {
int DEFAULT_FILE_SIZE = 8 * BUFFER_SIZE;
FastStringBuffer buffer = new FastStringBuffer(DEFAULT_FILE_SIZE);
StringBuffer buffer = new StringBuffer(DEFAULT_FILE_SIZE);
while (n > 0) {
buffer.append(readBuffer, 0, n);
n = reader.read(readBuffer);
}
return buffer.toCharArray();
return buffer.toString().toCharArray();
}
}
+1
View File
@@ -24,6 +24,7 @@
<orderEntry type="library" name="batik" level="project" />
<orderEntry type="library" name="xmlgraphics-commons" level="project" />
<orderEntry type="library" name="xml-apis-ext" level="project" />
<orderEntry type="library" name="Guava" level="project" />
</component>
<component name="copyright">
<Base>
@@ -19,6 +19,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Lists;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.process.ProcessInfo;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -29,8 +30,7 @@ import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SelectFromListDialog;
import com.jetbrains.python.PythonHelpersLocator;
import com.jetbrains.python.internal.ProcessUtils;
import com.jetbrains.python.internal.PyProcessInfo;
import com.intellij.execution.process.ProcessUtils;
import com.jetbrains.python.sdk.PythonSdkType;
import org.jetbrains.annotations.NotNull;
@@ -63,13 +63,13 @@ public class PyAttachToProcessAction extends AnAction {
final SelectFromListDialog selectDialog =
new SelectFromListDialog(project, pythonProcessesList(), new SelectFromListDialog.ToStringAspect() {
public String getToStirng(Object obj) {
PyProcessInfo info = (PyProcessInfo)obj;
ProcessInfo info = (ProcessInfo)obj;
return info.getPid() + " " + info.getArgs();
}
}, "Select Python Process", ListSelectionModel.SINGLE_SELECTION);
if (selectDialog.showAndGet()) {
PyProcessInfo process = (PyProcessInfo)selectDialog.getSelection()[0];
ProcessInfo process = (ProcessInfo)selectDialog.getSelection()[0];
PyAttachToProcessDebugRunner runner =
new PyAttachToProcessDebugRunner(project, process.getPid(), sdk.getHomePath());
@@ -84,13 +84,13 @@ public class PyAttachToProcessAction extends AnAction {
}
}
private static PyProcessInfo[] pythonProcessesList() {
PyProcessInfo[] list = ProcessUtils.getProcessList(PythonHelpersLocator.getHelpersRoot().getAbsolutePath()).getProcessList();
return FluentIterable.from(Lists.newArrayList(list)).filter(new Predicate<PyProcessInfo>() {
private static ProcessInfo[] pythonProcessesList() {
ProcessInfo[] list = ProcessUtils.getProcessList(PythonHelpersLocator.getHelpersRoot().getAbsolutePath()).getProcessList();
return FluentIterable.from(Lists.newArrayList(list)).filter(new Predicate<ProcessInfo>() {
@Override
public boolean apply(PyProcessInfo input) {
public boolean apply(ProcessInfo input) {
return input.getCommand().toLowerCase().contains("python");
}
}).toArray(PyProcessInfo.class);
}).toArray(ProcessInfo.class);
}
}