1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights. These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "sshremoteprocessrunner.h"
36 #define ASSERT_STATE(states) assertState(states, Q_FUNC_INFO)
39 \class Utils::SshRemoteProcessRunner
41 \brief Convenience class for running a remote process over an SSH connection.
46 class SshRemoteProcessRunnerPrivate : public QObject
50 SshRemoteProcessRunnerPrivate(const SshConnectionParameters ¶ms,
52 SshRemoteProcessRunnerPrivate(const SshConnection::Ptr &connection,
54 void run(const QByteArray &command);
55 QByteArray command() const { return m_command; }
57 const SshConnection::Ptr m_connection;
58 SshRemoteProcess::Ptr m_process;
61 void connectionError(Utils::SshError);
62 void processStarted();
63 void processOutputAvailable(const QByteArray &output);
64 void processErrorOutputAvailable(const QByteArray &output);
65 void processClosed(int exitStatus);
68 void handleConnected();
69 void handleConnectionError(Utils::SshError error);
70 void handleDisconnected();
71 void handleProcessStarted();
72 void handleProcessFinished(int exitStatus);
75 enum State { Inactive, Connecting, Connected, ProcessRunning };
77 void setState(State state);
78 void assertState(const QList<State> &allowedStates, const char *func);
79 void assertState(State allowedState, const char *func);
83 const SshConnectionParameters m_params;
87 SshRemoteProcessRunnerPrivate::SshRemoteProcessRunnerPrivate(const SshConnectionParameters ¶ms,
90 m_connection(SshConnection::create()),
96 SshRemoteProcessRunnerPrivate::SshRemoteProcessRunnerPrivate(const SshConnection::Ptr &connection,
99 m_connection(connection),
101 m_params(connection->connectionParameters())
105 void SshRemoteProcessRunnerPrivate::run(const QByteArray &command)
107 ASSERT_STATE(Inactive);
108 setState(Connecting);
111 connect(m_connection.data(), SIGNAL(error(Utils::SshError)),
112 SLOT(handleConnectionError(Utils::SshError)));
113 connect(m_connection.data(), SIGNAL(disconnected()),
114 SLOT(handleDisconnected()));
115 if (m_connection->state() == SshConnection::Connected) {
118 connect(m_connection.data(), SIGNAL(connected()),
119 SLOT(handleConnected()));
120 m_connection->connectToHost(m_params);
124 void SshRemoteProcessRunnerPrivate::handleConnected()
126 ASSERT_STATE(Connecting);
129 m_process = m_connection->createRemoteProcess(m_command);
130 connect(m_process.data(), SIGNAL(started()), SLOT(handleProcessStarted()));
131 connect(m_process.data(), SIGNAL(closed(int)),
132 SLOT(handleProcessFinished(int)));
133 connect(m_process.data(), SIGNAL(outputAvailable(QByteArray)),
134 SIGNAL(processOutputAvailable(QByteArray)));
135 connect(m_process.data(), SIGNAL(errorOutputAvailable(QByteArray)),
136 SIGNAL(processErrorOutputAvailable(QByteArray)));
140 void SshRemoteProcessRunnerPrivate::handleConnectionError(Utils::SshError error)
142 handleDisconnected();
143 emit connectionError(error);
146 void SshRemoteProcessRunnerPrivate::handleDisconnected()
148 ASSERT_STATE(QList<State>() << Connecting << Connected << ProcessRunning);
152 void SshRemoteProcessRunnerPrivate::handleProcessStarted()
154 ASSERT_STATE(Connected);
155 setState(ProcessRunning);
157 emit processStarted();
160 void SshRemoteProcessRunnerPrivate::handleProcessFinished(int exitStatus)
162 switch (exitStatus) {
163 case SshRemoteProcess::FailedToStart:
164 ASSERT_STATE(Connected);
166 case SshRemoteProcess::KilledBySignal:
167 case SshRemoteProcess::ExitedNormally:
168 ASSERT_STATE(ProcessRunning);
171 Q_ASSERT_X(false, Q_FUNC_INFO, "Impossible exit status.");
174 emit processClosed(exitStatus);
177 void SshRemoteProcessRunnerPrivate::setState(State state)
179 if (m_state != state) {
181 if (m_state == Inactive) {
183 disconnect(m_process.data(), 0, this, 0);
184 disconnect(m_connection.data(), 0, this, 0);
189 void SshRemoteProcessRunnerPrivate::assertState(const QList<State> &allowedStates,
192 if (!allowedStates.contains(m_state))
193 qWarning("Unexpected state %d in function %s", m_state, func);
196 void SshRemoteProcessRunnerPrivate::assertState(State allowedState,
199 assertState(QList<State>() << allowedState, func);
203 SshRemoteProcessRunner::Ptr SshRemoteProcessRunner::create(const SshConnectionParameters ¶ms)
205 return SshRemoteProcessRunner::Ptr(new SshRemoteProcessRunner(params));
208 SshRemoteProcessRunner::Ptr SshRemoteProcessRunner::create(const SshConnection::Ptr &connection)
210 return SshRemoteProcessRunner::Ptr(new SshRemoteProcessRunner(connection));
213 SshRemoteProcessRunner::SshRemoteProcessRunner(const SshConnectionParameters ¶ms)
214 : d(new SshRemoteProcessRunnerPrivate(params, this))
219 SshRemoteProcessRunner::SshRemoteProcessRunner(const SshConnection::Ptr &connection)
220 : d(new SshRemoteProcessRunnerPrivate(connection, this))
225 void SshRemoteProcessRunner::init()
227 connect(d, SIGNAL(connectionError(Utils::SshError)),
228 SIGNAL(connectionError(Utils::SshError)));
229 connect(d, SIGNAL(processStarted()), SIGNAL(processStarted()));
230 connect(d, SIGNAL(processClosed(int)), SIGNAL(processClosed(int)));
231 connect(d, SIGNAL(processOutputAvailable(QByteArray)),
232 SIGNAL(processOutputAvailable(QByteArray)));
233 connect(d, SIGNAL(processErrorOutputAvailable(QByteArray)),
234 SIGNAL(processErrorOutputAvailable(QByteArray)));
237 void SshRemoteProcessRunner::run(const QByteArray &command)
242 QByteArray SshRemoteProcessRunner::command() const { return d->command(); }
243 SshConnection::Ptr SshRemoteProcessRunner::connection() const { return d->m_connection; }
244 SshRemoteProcess::Ptr SshRemoteProcessRunner::process() const { return d->m_process; }
249 #include "sshremoteprocessrunner.moc"