/******************************************************************************* * Copyright (c) 2007, 2011 Wind River Systems, Inc. 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 * * Contributors: * Wind River Systems - initial API and implementation * Martin Oberhuber (Wind River) - [238564] Adopt TM 3.0 APIs * Uwe Stieber (Wind River) - [271227] Fix compiler warnings in org.eclipse.tcf.rse * Intel Corporation - [329654] Make all sub services operate against TCF connector service *******************************************************************************/ package org.eclipse.tcf.internal.rse.processes; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.rse.core.model.IHost; import org.eclipse.rse.services.clientserver.messages.SystemMessageException; import org.eclipse.rse.services.clientserver.processes.HostProcessFilterImpl; import org.eclipse.rse.services.clientserver.processes.IHostProcess; import org.eclipse.rse.services.clientserver.processes.IHostProcessFilter; import org.eclipse.rse.services.clientserver.processes.ISystemProcessRemoteConstants; import org.eclipse.rse.services.processes.AbstractProcessService; import org.eclipse.rse.services.processes.IProcessService; import org.eclipse.tcf.internal.rse.ITCFService; import org.eclipse.tcf.internal.rse.TCFConnectorService; import org.eclipse.tcf.internal.rse.TCFConnectorServiceManager; import org.eclipse.tcf.internal.rse.TCFRSETask; import org.eclipse.tcf.protocol.IToken; import org.eclipse.tcf.services.IProcesses; public class TCFProcessService extends AbstractProcessService implements IProcessService { private final TCFConnectorService connector; private final TCFProcessResource root; private final Map<Long,TCFProcessResource> pid2res = new HashMap<Long,TCFProcessResource>(); private final Map<String,Long> signals = new HashMap<String,Long>(); private final List<Runnable> get_signals_wait_list = new ArrayList<Runnable>(); public TCFProcessService(IHost host) { connector = (TCFConnectorService)TCFConnectorServiceManager .getInstance().getConnectorService(host, ITCFService.class); root = new TCFProcessResource(this, null, null, null); } public TCFConnectorService getTCFConnectorService() { return connector; } @Override public String getDescription() { return "The TCF Process Service uses the Target Communication Framework to provide service for the Processes subsystem." + //$NON-NLS-1$ " It requires a TCF agent to be running on the remote machine."; //$NON-NLS-1$ } @Override public String getName() { return "TCF Process Service"; //$NON-NLS-1$ } @Override public IHostProcess getParentProcess(long PID, IProgressMonitor monitor) throws SystemMessageException { return getProcess(getProcess(PID, monitor).getPPid(), monitor); } @Override public IHostProcess getProcess(final long PID, IProgressMonitor monitor) throws SystemMessageException { return new TCFRSETask<IHostProcess>() { public void run() { if (!root.loadChildren(this)) return; if (root.getChildrenError() != null) { error(root.getChildrenError()); return; } done(pid2res.get(PID)); } }.getS(monitor, "Get process properties"); //$NON-NLS-1$ } public String[] getSignalTypes() { return new TCFRSETask<String[]>() { public void run() { if (signals.isEmpty()) { if (get_signals_wait_list.contains(this)) { done(signals.keySet().toArray(new String[signals.size()])); } else { if (get_signals_wait_list.isEmpty()) { connector.getService(IProcesses.class).getSignalList(null, new IProcesses.DoneGetSignalList() { public void doneGetSignalList(IToken token, Exception error, Collection<Map<String,Object>> list) { if (list != null) { for (Map<String,Object> m : list) { String name = (String)m.get(IProcesses.SIG_NAME); Number code = (Number)m.get(IProcesses.SIG_CODE); if (name != null && code != null) signals.put(name, code.longValue()); } } for (Runnable r : get_signals_wait_list) r.run(); get_signals_wait_list.clear(); } }); } get_signals_wait_list.add(this); } } else { done(signals.keySet().toArray(new String[signals.size()])); } } }.getE(); } public boolean kill(final long PID, final String signal, IProgressMonitor monitor) throws SystemMessageException { return new TCFRSETask<Boolean>() { public void run() { if (!root.loadChildren(this)) return; if (root.getChildrenError() != null) { error(root.getChildrenError()); return; } TCFProcessResource prs = pid2res.get(PID); if (prs == null) { done(false); return; } Long signo = signals.get(signal); if (signal.equals(ISystemProcessRemoteConstants.PROCESS_SIGNAL_TYPE_DEFAULT)) { if (signo == null) signo = signals.get("SIGTERM"); if (signo == null) signo = signals.get("SIGKILL"); } if (signo == null) { error(new Exception("Unknown signal: " + signal)); return; } connector.getService(IProcesses.class).signal(prs.getID(), signo.longValue(), new IProcesses.DoneCommand() { public void doneCommand(IToken token, Exception error) { if (error != null) { error(error); } else { done(true); } } }); } }.getS(monitor, "Sending signal to a process"); //$NON-NLS-1$ } private void sort(IHostProcess[] arr) { Comparator<IHostProcess> c = new Comparator<IHostProcess>() { public int compare(IHostProcess o1, IHostProcess o2) { long p1 = o1.getPid(); long p2 = o2.getPid(); if (p1 < p2) return -1; if (p1 > p2) return 1; return 0; } }; Arrays.sort(arr, c); } @Override public IHostProcess[] listAllProcesses(IProgressMonitor monitor) throws SystemMessageException { HostProcessFilterImpl rpfs = new HostProcessFilterImpl(); return listAllProcesses(rpfs, monitor); } public IHostProcess[] listAllProcesses(final IHostProcessFilter filter, IProgressMonitor monitor) throws SystemMessageException { return listAllProcesses(filter, root, monitor); } private boolean eqaulIDs(String x, String y) { if (x == null) return y == null; return x.equals(y); } public IHostProcess[] listAllProcesses(final IHostProcessFilter filter, final IHostProcess up, IProgressMonitor monitor) throws SystemMessageException { new TCFRSETask<Boolean>() { public void run() { TCFProcessResource parent = (TCFProcessResource)up; if (parent != null) { if (filter.getPpid() == null || filter.getPpid().equals("*") || parent.getChildrenError() != null) { //$NON-NLS-1$ parent.flushChildrenCache(); } } done(true); } }.getE(); return new TCFRSETask<IHostProcess[]>() { public void run() { TCFProcessResource parent = (TCFProcessResource)up; if (parent == null) { error(new IOException("Invalid parent")); //$NON-NLS-1$ return; } if (!parent.loadChildren(this)) return; if (parent.getChildrenError() != null) { error(parent.getChildrenError()); return; } List<IHostProcess> l = new ArrayList<IHostProcess>(); for (TCFProcessResource p : pid2res.values()) { if (eqaulIDs(parent.getID(), p.getParentID())) { if (p.getError() == null && filter.allows(p.getStatusLine())) l.add(p); } } IHostProcess[] arr = new IHostProcess[l.size()]; l.toArray(arr); sort(arr); done(arr); } }.getS(monitor, "List processes"); //$NON-NLS-1$ } @Override public IHostProcess[] listAllProcesses(String exeNameFilter, String userNameFilter, String stateFilter, IProgressMonitor monitor) throws SystemMessageException { HostProcessFilterImpl rpfs = new HostProcessFilterImpl(); rpfs.setName(exeNameFilter); rpfs.setUsername(userNameFilter); rpfs.setSpecificState(stateFilter); return listAllProcesses(rpfs, monitor); } @Override public IHostProcess[] listChildProcesses(long parentPID, IProgressMonitor monitor) throws SystemMessageException { HostProcessFilterImpl rpfs = new HostProcessFilterImpl(); return listChildProcesses(parentPID, rpfs, monitor); } @Override public IHostProcess[] listChildProcesses(long parentPID, IHostProcessFilter filter, IProgressMonitor monitor) throws SystemMessageException { filter.setPpid(Long.toString(parentPID)); return listAllProcesses(filter, monitor); } @Override public IHostProcess[] listRootProcesses(IProgressMonitor monitor) throws SystemMessageException { IHostProcess[] roots = new IHostProcess[1]; roots[0] = getProcess(1, monitor); return roots; } Map<Long,TCFProcessResource> getProcessCache() { return pid2res; } }