Commit 20e749df authored by Christian Kandeler's avatar Christian Kandeler
Browse files

Maemo: Move "mad info" parsing for Qemu specs into dedicated classes.

parent 0f15f419
......@@ -29,6 +29,7 @@
#include "maemoglobal.h"
#include "maemoconstants.h"
#include "maemodeviceconfigurations.h"
#include <coreplugin/ssh/sshconnection.h>
......@@ -44,6 +45,9 @@
namespace Qt4ProjectManager {
namespace Internal {
namespace {
static const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
}
QString MaemoGlobal::homeDirOnDevice(const QString &uname)
{
......@@ -99,6 +103,19 @@ QString MaemoGlobal::failedToConnectToServerMessage(const Core::SshConnection::P
return errorMsg;
}
QString MaemoGlobal::maddeRoot(const QString &qmakePath)
{
QDir dir(QDir::cleanPath(qmakePath).remove(binQmake));
dir.cdUp(); dir.cdUp();
return dir.absolutePath();
}
QString MaemoGlobal::targetName(const QString &qmakePath)
{
const QString target = QDir::cleanPath(qmakePath).remove(binQmake);
return target.mid(target.lastIndexOf(QLatin1Char('/')) + 1);
}
bool MaemoGlobal::removeRecursively(const QString &filePath, QString &error)
{
QFileInfo fileInfo(filePath);
......
......@@ -63,6 +63,8 @@ public:
static QString remoteSourceProfilesCommand();
static QString failedToConnectToServerMessage(const QSharedPointer<Core::SshConnection> &connection,
const MaemoDeviceConfig &deviceConfig);
static QString maddeRoot(const QString &qmakePath);
static QString targetName(const QString &qmakePath);
static bool removeRecursively(const QString &filePath, QString &error);
static void callMaddeShellScript(QProcess &proc, const QString &maddeRoot,
......
......@@ -30,6 +30,7 @@
#include "maemoqemumanager.h"
#include "maemoglobal.h"
#include "maemoqemuruntimeparser.h"
#include "maemorunconfiguration.h"
#include "maemotoolchain.h"
#include "qtversionmanager.h"
......@@ -52,14 +53,11 @@
#include <QtCore/QList>
#include <QtCore/QSet>
#include <QtCore/QStringBuilder>
#include <QtCore/QTextStream>
#include <QtGui/QAction>
#include <QtGui/QDesktopServices>
#include <QtGui/QMessageBox>
#include <QtXml/QXmlStreamReader>
#include <limits.h>
using namespace ProjectExplorer;
......@@ -69,7 +67,6 @@ using namespace Qt4ProjectManager::Internal;
MaemoQemuManager *MaemoQemuManager::m_instance = 0;
const QSize iconSize = QSize(24, 20);
const QLatin1String binQmake("/bin/qmake" EXEC_SUFFIX);
MaemoQemuManager::MaemoQemuManager(QObject *parent)
: QObject(parent)
......@@ -157,10 +154,9 @@ void MaemoQemuManager::qtVersionsChanged(const QList<int> &uniqueIds)
if (manager->isValidId(uniqueId)) {
QtVersion *version = manager->version(uniqueId);
if (version->supportsTargetId(Constants::MAEMO_DEVICE_TARGET_ID)) {
MaemoQemuRuntime runtime = createRuntime(version);
MaemoQemuRuntime runtime
= MaemoQemuRuntimeParser::parseRuntime(version);
if (runtime.isValid()) {
runtime.m_watchPath =
runtime.m_root.left(runtime.m_root.lastIndexOf(QLatin1Char('/')));
m_runtimes.insert(uniqueId, runtime);
if (!m_runtimeRootWatcher->directories().contains(runtime.m_watchPath))
m_runtimeRootWatcher->addPath(runtime.m_watchPath);
......@@ -357,7 +353,7 @@ void MaemoQemuManager::startRuntime()
m_runningQtId = version->uniqueId();
const QString root
= QDir::toNativeSeparators(maddeRoot(version->qmakeCommand())
= QDir::toNativeSeparators(MaemoGlobal::maddeRoot(version->qmakeCommand())
+ QLatin1Char('/'));
const MaemoQemuRuntime rt = m_runtimes.value(version->uniqueId());
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
......@@ -592,296 +588,6 @@ bool MaemoQemuManager::targetUsesMatchingRuntimeConfig(Target *target,
return config.isValid() && config.type == MaemoDeviceConfig::Simulator;
}
QString MaemoQemuManager::maddeRoot(const QString &qmake) const
{
QDir dir(QDir::cleanPath(qmake).remove(binQmake));
dir.cdUp(); dir.cdUp();
return dir.absolutePath();
}
QString MaemoQemuManager::targetRoot(const QString &qmake) const
{
const QString target = QDir::cleanPath(qmake).remove(binQmake);
return target.mid(target.lastIndexOf(QLatin1Char('/')) + 1);
}
bool MaemoQemuManager::fillRuntimeInformationForOldMadInfo(MaemoQemuRuntime *runtime) const
{
const QStringList files = QDir(runtime->m_root).entryList(QDir::Files
| QDir::NoSymLinks | QDir::NoDotAndDotDot);
// we need at least the information file
const QLatin1String infoFile("information");
if (files.contains(infoFile)) {
QFile file(runtime->m_root + QLatin1Char('/') + infoFile);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMap<QString, QString> map;
QTextStream stream(&file);
while (!stream.atEnd()) {
const QString &line = stream.readLine().trimmed();
const int index = line.indexOf(QLatin1Char('='));
map.insert(line.mid(0, index).remove(QLatin1Char('\'')),
line.mid(index + 1).remove(QLatin1Char('\'')));
}
runtime->m_bin = map.value(QLatin1String("qemu"));
runtime->m_args = map.value(QLatin1String("qemu_args"));
setEnvironment(runtime, map.value(QLatin1String("libpath")));
runtime->m_sshPort = map.value(QLatin1String("sshport"));
runtime->m_freePorts = MaemoPortList();
int i = 2;
while (true) {
const QString port = map.value(QLatin1String("redirport")
+ QString::number(i++));
if (port.isEmpty())
break;
runtime->m_freePorts.addPort(port.toInt());
}
return true;
}
}
return false;
}
void MaemoQemuManager::setEnvironment(MaemoQemuRuntime *runTime,
const QString &envSpec) const
{
QString remainingEnvSpec = envSpec;
QString currentKey;
while (true) {
const int nextEqualsSignPos
= remainingEnvSpec.indexOf(QLatin1Char('='));
if (nextEqualsSignPos == -1) {
if (!currentKey.isEmpty())
runTime->m_environment.insert(currentKey, remainingEnvSpec);
break;
}
const int keyStartPos
= remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\s")),
nextEqualsSignPos) + 1;
if (!currentKey.isEmpty()) {
const int valueEndPos
= remainingEnvSpec.lastIndexOf(QRegExp(QLatin1String("\\S")),
qMax(0, keyStartPos - 1)) + 1;
runTime->m_environment.insert(currentKey,
remainingEnvSpec.left(valueEndPos));
}
currentKey = remainingEnvSpec.mid(keyStartPos,
nextEqualsSignPos - keyStartPos);
remainingEnvSpec.remove(0, nextEqualsSignPos + 1);
}
}
MaemoQemuRuntime MaemoQemuManager::createRuntime(const QtVersion *qtVersion) const
{
MaemoQemuRuntime runtime;
const QString maddeRootPath = maddeRoot(qtVersion->qmakeCommand());
const QString madCommand = maddeRootPath + QLatin1String("/bin/mad");
if (!QFileInfo(madCommand).exists())
return runtime;
QProcess madProc;
MaemoGlobal::callMaddeShellScript(madProc, maddeRootPath, madCommand,
QStringList() << QLatin1String("info"));
if (!madProc.waitForStarted() || !madProc.waitForFinished())
return runtime;
const QByteArray &madInfoOutput = madProc.readAllStandardOutput();
const QString &targetName = targetRoot(qtVersion->qmakeCommand());
runtime = parseRuntimeFromMadInfo(madInfoOutput, targetName);
if (!runtime.m_name.isEmpty()) {
runtime.m_root = maddeRootPath + QLatin1String("/runtimes/")
+ runtime.m_name;
// TODO: Workaround for missing ssh tag. Fix once MADDE is ready.
runtime.m_sshPort = QLatin1String("6666");
return runtime;
} else {
return parseRuntimeFromOldMadInfo(madInfoOutput, maddeRootPath, targetName);
}
}
MaemoQemuRuntime MaemoQemuManager::parseRuntimeFromMadInfo(const QByteArray &output,
const QString &targetName) const
{
QXmlStreamReader infoReader(output);
QString runtimeName;
QList<MaemoQemuRuntime> runtimes;
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("madde")) {
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("targets")) {
while (infoReader.readNextStartElement())
handleMadInfoTargetTag(infoReader, runtimeName, targetName);
} else if (infoReader.name() == QLatin1String("runtimes")) {
while (infoReader.readNextStartElement()) {
const MaemoQemuRuntime &rt = handleMadInfoRuntimeTag(infoReader);
if (!rt.m_name.isEmpty() && !rt.m_bin.isEmpty()
&& !rt.m_args.isEmpty()) {
runtimes << rt;
}
}
} else {
infoReader.skipCurrentElement();
}
}
}
}
foreach (const MaemoQemuRuntime &rt, runtimes) {
if (rt.m_name == runtimeName)
return rt;
}
return MaemoQemuRuntime();
}
MaemoQemuRuntime MaemoQemuManager::parseRuntimeFromOldMadInfo(const QString &output,
const QString &maddeRootPath, const QString &targetName) const
{
QXmlStreamReader infoReader(output);
QStringList installedRuntimes;
QString targetRuntime;
while (!infoReader.atEnd() && !installedRuntimes.contains(targetRuntime)) {
if (infoReader.readNext() == QXmlStreamReader::StartElement) {
if (targetRuntime.isEmpty()
&& infoReader.name() == QLatin1String("target")) {
const QXmlStreamAttributes &attrs = infoReader.attributes();
if (attrs.value(QLatin1String("target_id")) == targetName)
targetRuntime = attrs.value("runtime_id").toString();
} else if (infoReader.name() == QLatin1String("runtime")) {
const QXmlStreamAttributes attrs = infoReader.attributes();
while (!infoReader.atEnd()) {
if (infoReader.readNext() == QXmlStreamReader::EndElement
&& infoReader.name() == QLatin1String("runtime"))
break;
if (infoReader.tokenType() == QXmlStreamReader::StartElement
&& infoReader.name() == QLatin1String("installed")) {
if (infoReader.readNext() == QXmlStreamReader::Characters
&& infoReader.text() == QLatin1String("true")) {
if (attrs.hasAttribute(QLatin1String("runtime_id")))
installedRuntimes << attrs.value(QLatin1String("runtime_id")).toString();
else if (attrs.hasAttribute(QLatin1String("id"))) {
// older MADDE seems to use only id
installedRuntimes << attrs.value(QLatin1String("id")).toString();
}
}
break;
}
}
}
}
}
MaemoQemuRuntime runtime;
if (installedRuntimes.contains(targetRuntime)) {
runtime.m_name = targetRuntime;
runtime.m_root = maddeRootPath + QLatin1String("/runtimes/")
+ targetRuntime;
fillRuntimeInformationForOldMadInfo(&runtime);
}
return runtime;
}
void MaemoQemuManager::handleMadInfoTargetTag(QXmlStreamReader &infoReader,
QString &runtimeName, const QString &targetName) const
{
const QXmlStreamAttributes &attrs = infoReader.attributes();
if (infoReader.name() == QLatin1String("target") && runtimeName.isEmpty()
&& attrs.value(QLatin1String("name")) == targetName
&& attrs.value(QLatin1String("installed")) == QLatin1String("true")) {
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("runtime"))
runtimeName = infoReader.readElementText();
else
infoReader.skipCurrentElement();
}
} else {
infoReader.skipCurrentElement();
}
}
MaemoQemuRuntime MaemoQemuManager::handleMadInfoRuntimeTag(QXmlStreamReader &infoReader) const
{
MaemoQemuRuntime runtime;
const QXmlStreamAttributes &attrs = infoReader.attributes();
if (infoReader.name() != QLatin1String("runtime")
|| attrs.value(QLatin1String("installed")) != QLatin1String("true")) {
infoReader.skipCurrentElement();
return runtime;
}
runtime.m_name = attrs.value(QLatin1String("name")).toString();
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("exec-path")) {
runtime.m_bin = infoReader.readElementText();
} else if (infoReader.name() == QLatin1String("args")) {
runtime.m_args = infoReader.readElementText();
} else if (infoReader.name() == QLatin1String("environment")) {
runtime.m_environment = handleMadInfoEnvironmentTag(infoReader);
} else if (infoReader.name() == QLatin1String("tcpportmap")) {
runtime.m_freePorts = handleMadInfoTcpPortListTag(infoReader);
} else {
infoReader.skipCurrentElement();
}
}
return runtime;
}
QHash<QString, QString> MaemoQemuManager::handleMadInfoEnvironmentTag(QXmlStreamReader &infoReader) const
{
QHash<QString, QString> env;
while (infoReader.readNextStartElement()) {
const QPair<QString, QString> &var
= handleMadInfoVariableTag(infoReader);
if (!var.first.isEmpty())
env.insert(var.first, var.second);
}
return env;
}
QPair<QString, QString> MaemoQemuManager::handleMadInfoVariableTag(QXmlStreamReader &infoReader) const
{
QPair<QString, QString> var;
if (infoReader.name() != QLatin1String("variable")) {
infoReader.skipCurrentElement();
return var;
}
// TODO: Check for "purpose" attribute and handle "glbackend" in a special way
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("name"))
var.first = infoReader.readElementText();
else if (infoReader.name() == QLatin1String("value"))
var.second = infoReader.readElementText();
else
infoReader.skipCurrentElement();
}
return var;
}
MaemoPortList MaemoQemuManager::handleMadInfoTcpPortListTag(QXmlStreamReader &infoReader) const
{
MaemoPortList ports;
while (infoReader.readNextStartElement()) {
const int port = handleMadInfoPortTag(infoReader);
if (port != -1 && port != 6666) // TODO: Remove second condition once MADDE has ssh tag
ports.addPort(port);
}
return ports;
}
int MaemoQemuManager::handleMadInfoPortTag(QXmlStreamReader &infoReader) const
{
int port = -1;
if (infoReader.name() == QLatin1String("port")) {
while (infoReader.readNextStartElement()) {
if (infoReader.name() == QLatin1String("host"))
port = infoReader.readElementText().toInt();
else
infoReader.skipCurrentElement();
}
}
return port;
}
void MaemoQemuManager::notify(const QList<int> uniqueIds)
{
qtVersionsChanged(uniqueIds);
......
......@@ -42,7 +42,6 @@
QT_FORWARD_DECLARE_CLASS(QAction);
QT_FORWARD_DECLARE_CLASS(QFileSystemWatcher)
QT_FORWARD_DECLARE_CLASS(QStringList);
QT_FORWARD_DECLARE_CLASS(QXmlStreamReader);
namespace ProjectExplorer {
class BuildConfiguration;
......@@ -113,24 +112,6 @@ private:
bool targetUsesMatchingRuntimeConfig(ProjectExplorer::Target *target,
QtVersion **qtVersion = 0);
QString maddeRoot(const QString &qmake) const;
QString targetRoot(const QString &qmake) const;
bool fillRuntimeInformationForOldMadInfo(MaemoQemuRuntime *runtime) const;
void setEnvironment(MaemoQemuRuntime *runTime, const QString &envSpec) const;
MaemoQemuRuntime createRuntime(const QtVersion *qtVersion) const;
MaemoQemuRuntime parseRuntimeFromMadInfo(const QByteArray &output,
const QString &targetName) const;
MaemoQemuRuntime parseRuntimeFromOldMadInfo(const QString &output,
const QString &maddeRootPath, const QString &targetName) const;
void handleMadInfoTargetTag(QXmlStreamReader &infoReader,
QString &runtimeName, const QString &targetName) const;
MaemoQemuRuntime handleMadInfoRuntimeTag(QXmlStreamReader &infoReader) const;
QHash<QString, QString> handleMadInfoEnvironmentTag(QXmlStreamReader &infoReader) const;
QPair<QString, QString> handleMadInfoVariableTag(QXmlStreamReader &infoReader) const;
MaemoPortList handleMadInfoTcpPortListTag(QXmlStreamReader &infoReader) const;
int handleMadInfoPortTag(QXmlStreamReader &infoReader) const;
void notify(const QList<int> uniqueIds);
void toggleDeviceConnections(MaemoRunConfiguration *mrc, bool connect);
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/
#include "maemoqemuruntimeparser.h"
#include "maemoglobal.h"
#include <qt4projectmanager/qtversionmanager.h>
#include <QtCore/QDir>
#include <QtCore/QProcess>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
namespace Qt4ProjectManager {
namespace Internal {
class MaemoQemuRuntimeParserV1 : public MaemoQemuRuntimeParser
{
public:
MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot);
MaemoQemuRuntime parseRuntime();
private:
void fillRuntimeInformation(MaemoQemuRuntime *runtime) const;
void setEnvironment(MaemoQemuRuntime *runTime, const QString &envSpec) const;
const QString m_maddeRoot;
};
class MaemoQemuRuntimeParserV2 : public MaemoQemuRuntimeParser
{
public:
MaemoQemuRuntimeParserV2(const QString &madInfoOutput,
const QString &targetName);
MaemoQemuRuntime parseRuntime();
private:
void handleTargetTag(QString &runtimeName);
MaemoQemuRuntime handleRuntimeTag();
QHash<QString, QString> handleEnvironmentTag();
QPair<QString, QString> handleVariableTag();
MaemoPortList handleTcpPortListTag();
int handlePortTag();
};
MaemoQemuRuntimeParser::MaemoQemuRuntimeParser(const QString &madInfoOutput,
const QString &targetName)
: m_madInfoReader(madInfoOutput), m_targetName(targetName)
{
}
MaemoQemuRuntime MaemoQemuRuntimeParser::parseRuntime(const QtVersion *qtVersion)
{
MaemoQemuRuntime runtime;
const QString maddeRootPath
= MaemoGlobal::maddeRoot(qtVersion->qmakeCommand());
const QString madCommand = maddeRootPath + QLatin1String("/bin/mad");
if (!QFileInfo(madCommand).exists())
return runtime;
QProcess madProc;
MaemoGlobal::callMaddeShellScript(madProc, maddeRootPath, madCommand,
QStringList() << QLatin1String("info"));
if (!madProc.waitForStarted() || !madProc.waitForFinished())
return runtime;
const QByteArray &madInfoOutput = madProc.readAllStandardOutput();
const QString &targetName
= MaemoGlobal::targetName(qtVersion->qmakeCommand());
runtime = MaemoQemuRuntimeParserV2(madInfoOutput, targetName).parseRuntime();
if (!runtime.m_name.isEmpty()) {
runtime.m_root = maddeRootPath + QLatin1String("/runtimes/")
+ runtime.m_name;
// TODO: Workaround for missing ssh tag. Fix once MADDE is ready.
runtime.m_sshPort = QLatin1String("6666");
} else {
runtime = MaemoQemuRuntimeParserV1(madInfoOutput, targetName,
maddeRootPath).parseRuntime();
}
runtime.m_watchPath = runtime.m_root
.left(runtime.m_root.lastIndexOf(QLatin1Char('/')));
return runtime;
}
MaemoQemuRuntimeParserV1::MaemoQemuRuntimeParserV1(const QString &madInfoOutput,
const QString &targetName, const QString &maddeRoot)
: MaemoQemuRuntimeParser(madInfoOutput, targetName), m_maddeRoot(maddeRoot)
{
}
MaemoQemuRuntime MaemoQemuRuntimeParserV1::parseRuntime()
{
QStringList installedRuntimes;
QString targetRuntime;
while (!m_madInfoReader.atEnd() && !installedRuntimes.contains(targetRuntime)) {
if (m_madInfoReader.readNext() == QXmlStreamReader::StartElement) {
if (targetRuntime.isEmpty()
&& m_madInfoReader.name() == QLatin1String("target")) {
const QXmlStreamAttributes &attrs = m_madInfoReader.attributes();
if (attrs.value(QLatin1String("target_id")) == targetName())
targetRuntime = attrs.value("runtime_id").toString();
} else if (m_madInfoReader.name() == QLatin1String("runtime")) {
const QXmlStreamAttributes attrs = m_madInfoReader.attributes();
while (!m_madInfoReader.atEnd()) {
if (m_madInfoReader.readNext() == QXmlStreamReader::EndElement
&& m_madInfoReader.name() == QLatin1String("runtime"))
break;
if (m_madInfoReader.tokenType() == QXmlStreamReader::StartElement
&& m_madInfoReader.name() == QLatin1String("installed")) {
if (m_madInfoReader.readNext() == QXmlStreamReader::Characters
&& m_madInfoReader.text() == QLatin1String("true")) {
if (attrs.hasAttribute(QLatin1String("runtime_id")))
installedRuntimes << attrs.value(QLatin1String("runtime_id")).toString();
else if (attrs.hasAttribute(QLatin1String("id"))) {
// older MADDE seems to use only id
installedRuntimes << attrs.value(QLatin1String("id")).toString();
}
}
break;
}
}