/************************************************************************** ** ** This file is part of Qt Creator ** ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). ** ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** ** GNU Lesser General Public License Usage ** ** 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. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** Other Usage ** ** Alternatively, this file may be used in accordance with the terms and ** conditions contained in a signed written agreement between you and Nokia. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** **************************************************************************/ #include "maemoqemuruntimeparser.h" #include "maemoglobal.h" #include "maemoqemusettings.h" #include #include #include #include #include #include using namespace RemoteLinux; namespace Madde { 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; }; class MaemoQemuRuntimeParserV2 : public MaemoQemuRuntimeParser { public: MaemoQemuRuntimeParserV2(const QString &madInfoOutput, const QString &targetName, const QString &maddeRoot); MaemoQemuRuntime parseRuntime(); private: struct Port { Port() : port(-1), ssh(false) {} int port; bool ssh; }; void handleTargetTag(QString &runtimeName); MaemoQemuRuntime handleRuntimeTag(); void handleEnvironmentTag(MaemoQemuRuntime &runtime); void handleVariableTag(MaemoQemuRuntime &runtime); QList handleTcpPortListTag(); Port handlePortTag(); MaemoQemuSettings::OpenGlMode openGlTagToEnum(const QString &tag) const; }; MaemoQemuRuntimeParser::MaemoQemuRuntimeParser(const QString &madInfoOutput, const QString &targetName, const QString &maddeRoot) : m_targetName(targetName), m_maddeRoot(maddeRoot), m_madInfoReader(madInfoOutput) { } MaemoQemuRuntime MaemoQemuRuntimeParser::parseRuntime(const QtSupport::BaseQtVersion *qtVersion) { MaemoQemuRuntime runtime; const QString maddeRootPath = MaemoGlobal::maddeRoot(qtVersion->qmakeCommand()); QProcess madProc; if (!MaemoGlobal::callMad(madProc, QStringList() << QLatin1String("info"), qtVersion->qmakeCommand(), false)) return runtime; if (!madProc.waitForStarted() || !madProc.waitForFinished()) return runtime; const QByteArray &madInfoOutput = madProc.readAllStandardOutput(); const QString &targetName = MaemoGlobal::targetName(qtVersion->qmakeCommand()); runtime = MaemoQemuRuntimeParserV2(madInfoOutput, targetName, maddeRootPath) .parseRuntime(); if (!runtime.m_name.isEmpty()) { runtime.m_root = maddeRootPath + QLatin1String("/runtimes/") + runtime.m_name; } 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, 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")) == m_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; } } } } } MaemoQemuRuntime runtime; if (installedRuntimes.contains(targetRuntime)) { runtime.m_name = targetRuntime; runtime.m_root = m_maddeRoot + QLatin1String("/runtimes/") + targetRuntime; fillRuntimeInformation(&runtime); } return runtime; } void MaemoQemuRuntimeParserV1::fillRuntimeInformation(MaemoQemuRuntime *runtime) const { const QStringList files = QDir(runtime->m_root).entryList(QDir::Files | QDir::NoSymLinks | QDir::NoDotAndDotDot); const QLatin1String infoFile("information"); if (files.contains(infoFile)) { QFile file(runtime->m_root + QLatin1Char('/') + infoFile); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QMap 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 = PortList(); 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()); } // This is complex because of extreme MADDE weirdness. const QString root = m_maddeRoot + QLatin1Char('/'); const bool pathIsRelative = QFileInfo(runtime->m_bin).isRelative(); runtime->m_bin = #ifdef Q_OS_WIN root + (pathIsRelative ? QLatin1String("madlib/") + runtime->m_bin // Fremantle. : runtime->m_bin) // Harmattan. + QLatin1String(".exe"); #else pathIsRelative ? root + QLatin1String("madlib/") + runtime->m_bin // Fremantle. : runtime->m_bin; // Harmattan. #endif } } } void MaemoQemuRuntimeParserV1::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_normalVars << MaemoQemuRuntime::Variable(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_normalVars << MaemoQemuRuntime::Variable(currentKey, remainingEnvSpec.left(valueEndPos)); } currentKey = remainingEnvSpec.mid(keyStartPos, nextEqualsSignPos - keyStartPos); remainingEnvSpec.remove(0, nextEqualsSignPos + 1); } } MaemoQemuRuntimeParserV2::MaemoQemuRuntimeParserV2(const QString &madInfoOutput, const QString &targetName, const QString &maddeRoot) : MaemoQemuRuntimeParser(madInfoOutput, targetName, maddeRoot) { } MaemoQemuRuntime MaemoQemuRuntimeParserV2::parseRuntime() { QString runtimeName; QList runtimes; while (m_madInfoReader.readNextStartElement()) { if (m_madInfoReader.name() == QLatin1String("madde")) { while (m_madInfoReader.readNextStartElement()) { if (m_madInfoReader.name() == QLatin1String("targets")) { while (m_madInfoReader.readNextStartElement()) handleTargetTag(runtimeName); } else if (m_madInfoReader.name() == QLatin1String("runtimes")) { while (m_madInfoReader.readNextStartElement()) { const MaemoQemuRuntime &rt = handleRuntimeTag(); if (!rt.m_name.isEmpty() && !rt.m_bin.isEmpty() && !rt.m_args.isEmpty()) { runtimes << rt; } } } else { m_madInfoReader.skipCurrentElement(); } } } } foreach (const MaemoQemuRuntime &rt, runtimes) { if (rt.m_name == runtimeName) return rt; } return MaemoQemuRuntime(); } void MaemoQemuRuntimeParserV2::handleTargetTag(QString &runtimeName) { const QXmlStreamAttributes &attrs = m_madInfoReader.attributes(); if (m_madInfoReader.name() == QLatin1String("target") && runtimeName.isEmpty() && attrs.value(QLatin1String("name")) == m_targetName && attrs.value(QLatin1String("installed")) == QLatin1String("true")) { while (m_madInfoReader.readNextStartElement()) { if (m_madInfoReader.name() == QLatin1String("runtime")) runtimeName = m_madInfoReader.readElementText(); else m_madInfoReader.skipCurrentElement(); } } else { m_madInfoReader.skipCurrentElement(); } } MaemoQemuRuntime MaemoQemuRuntimeParserV2::handleRuntimeTag() { MaemoQemuRuntime runtime; const QXmlStreamAttributes &attrs = m_madInfoReader.attributes(); if (m_madInfoReader.name() != QLatin1String("runtime") || attrs.value(QLatin1String("installed")) != QLatin1String("true")) { m_madInfoReader.skipCurrentElement(); return runtime; } runtime.m_name = attrs.value(QLatin1String("name")).toString(); while (m_madInfoReader.readNextStartElement()) { if (m_madInfoReader.name() == QLatin1String("exec-path")) { runtime.m_bin = m_madInfoReader.readElementText(); } else if (m_madInfoReader.name() == QLatin1String("args")) { runtime.m_args = m_madInfoReader.readElementText(); } else if (m_madInfoReader.name() == QLatin1String("environment")) { handleEnvironmentTag(runtime); } else if (m_madInfoReader.name() == QLatin1String("tcpportmap")) { const QList &ports = handleTcpPortListTag(); foreach (const Port &port, ports) { if (port.ssh) runtime.m_sshPort = QString::number(port.port); else runtime.m_freePorts.addPort(port.port); } } else { m_madInfoReader.skipCurrentElement(); } } return runtime; } void MaemoQemuRuntimeParserV2::handleEnvironmentTag(MaemoQemuRuntime &runtime) { while (m_madInfoReader.readNextStartElement()) handleVariableTag(runtime); #ifdef Q_OS_WIN const QString root = QDir::toNativeSeparators(m_maddeRoot) + QLatin1Char('/'); const QLatin1Char colon(';'); const QLatin1String key("PATH"); QProcessEnvironment env = QProcessEnvironment::systemEnvironment(); runtime.m_normalVars << MaemoQemuRuntime::Variable(key, root + QLatin1String("bin") + colon + env.value(key)); runtime.m_normalVars << MaemoQemuRuntime::Variable(key, root + QLatin1String("madlib") + colon + env.value(key)); #endif } void MaemoQemuRuntimeParserV2::handleVariableTag(MaemoQemuRuntime &runtime) { if (m_madInfoReader.name() != QLatin1String("variable")) { m_madInfoReader.skipCurrentElement(); return; } const bool isGlBackend = m_madInfoReader.attributes().value(QLatin1String("purpose")) == QLatin1String("glbackend"); QString varName; QString varValue; while (m_madInfoReader.readNextStartElement()) { const QXmlStreamAttributes &attrs = m_madInfoReader.attributes(); if (m_madInfoReader.name() == QLatin1String("name")) { varName = m_madInfoReader.readElementText(); } else if (m_madInfoReader.name() == QLatin1String("value") && attrs.value(QLatin1String("set")) != QLatin1String("false")) { varValue = m_madInfoReader.readElementText(); if (isGlBackend) { MaemoQemuSettings::OpenGlMode openGlMode = openGlTagToEnum(attrs.value(QLatin1String("option")).toString()); runtime.m_openGlBackendVarValues.insert(openGlMode, varValue); } } else { m_madInfoReader.skipCurrentElement(); } } if (varName.isEmpty()) return; if (isGlBackend) { runtime.m_openGlBackendVarName = varName; } else { runtime.m_normalVars << MaemoQemuRuntime::Variable(varName, varValue); } } QList MaemoQemuRuntimeParserV2::handleTcpPortListTag() { QList ports; while (m_madInfoReader.readNextStartElement()) { const Port &port = handlePortTag(); if (port.port != -1) ports << port; } return ports; } MaemoQemuRuntimeParserV2::Port MaemoQemuRuntimeParserV2::handlePortTag() { Port port; if (m_madInfoReader.name() == QLatin1String("port")) { const QXmlStreamAttributes &attrs = m_madInfoReader.attributes(); port.ssh = attrs.value(QLatin1String("service")) == QLatin1String("ssh"); while (m_madInfoReader.readNextStartElement()) { if (m_madInfoReader.name() == QLatin1String("host")) port.port = m_madInfoReader.readElementText().toInt(); else m_madInfoReader.skipCurrentElement(); } } return port; } MaemoQemuSettings::OpenGlMode MaemoQemuRuntimeParserV2::openGlTagToEnum(const QString &tag) const { if (tag == QLatin1String("hardware-acceleration")) return MaemoQemuSettings::HardwareAcceleration; if (tag == QLatin1String("software-rendering")) return MaemoQemuSettings::SoftwareRendering; if (tag == QLatin1String("autodetect")) return MaemoQemuSettings::AutoDetect; QTC_CHECK(false); return MaemoQemuSettings::AutoDetect; } } // namespace Internal } // namespace Madde