#include "PhoenixServicesClient.h" #include <QDebug> #include <QJsonDocument> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QtWebSockets/QtWebSockets> #include <QtCore/qjsondocument.h> #include "../phoenix.h" namespace phoenix { typedef QSharedPointer<QNetworkRequest> QNetworkRequestPtr; typedef QSharedPointer<QByteArray> QByteArrayPtr; // It's expected that the default server setup will point a hostname to our // web services application. // // This might be lame for some development environments, that typically // don't have much control over their local DNS settings, so this can be // configured, but I don't expect it to be used in production. QString DEFAULT_PHOENIX_PREFIX_PATH = "/p4_phoenix_services/v1"; QString DEFAULT_PHOENIX_UPDATES_PATH = "/updates"; int DEFAULT_RETRY_COUNT = 500; int DEFAULT_RETRY_PAUSE = 250; class PhoenixServicesClient::Impl : public QObject { Q_OBJECT public: Impl(PhoenixServicesClient *parent) : mClient(parent), mManager(parent), mUrl("http://example.com"), mSession(NULL), mPhoenixPrefixPath(DEFAULT_PHOENIX_PREFIX_PATH), mUpdatesPath(DEFAULT_PHOENIX_UPDATES_PATH), mWebSocket(NULL), mUpdateConnected(false), mUpdateDisconnected(false), mUpdateFailure(false), mRetryCount(DEFAULT_RETRY_COUNT), mRetryPause(DEFAULT_RETRY_PAUSE) { } QNetworkRequestPtr createRequest() { QNetworkRequestPtr request = QNetworkRequestPtr::create(); request->setRawHeader("User-Agent", (QString("p4_phoenix_services %1.%2.%3") .arg(PHOENIX_MAJOR_VERSION) .arg(PHOENIX_MINOR_VERSION) .arg(PHOENIX_PATCH_VERSION)).toUtf8()); request->setHeader(QNetworkRequest::ContentTypeHeader, "application/json"); request->setRawHeader("Accept", "application/json"); request->setRawHeader("Accept-Encoding", "gzip, deflate"); return request; } // Configures the url on the path with the indicated final path part. // The path should not be encoded. // // Note: will not set the query parameter. void setRequestUrlWithPath(QNetworkRequestPtr request, QString path) { QUrl url(mUrl); QString fullPath(mPhoenixPrefixPath); fullPath += path; url.setPath(fullPath); qDebug() << "setting request url " << url; request->setUrl(url); } void setBasicAuthFromSession(QNetworkRequestPtr request); QByteArray createSessionPostBody(const QString & user, const QString & password) { QJsonObject obj; obj["user"] = user; obj["password"] = password; QJsonDocument doc(obj); return doc.toJson(QJsonDocument::Compact); } void logInFinished(QNetworkReply *reply, const QString & user); RequestErrorPtr fromNetworkError(QNetworkReply::NetworkError code); RequestErrorPtr fromSslErrors(const QList<QSslError> & errors); void watch(const QList<QString> & projectIds); void unwatch(const QList<QString> & projectIds); void setSession(const Session & session); void connectWebSocket(); void disconnectWebSocket(); QUrl updateUrl(); void waitForUpdateSocket(); public slots: void handleLogInError(QNetworkReply::NetworkError code); void handleLogInSslErrors(const QList<QSslError> & errors); void fetchProjectsFinished(); void fetchProjectsError(QNetworkReply::NetworkError code); void fetchProjectsSslErrors(const QList<QSslError> & errors); void fetchProjectFinished(); void fetchProjectError(QNetworkReply::NetworkError code); void fetchProjectSslErrors(const QList<QSslError> & errors); void createProjectFinished(); void createProjectError(QNetworkReply::NetworkError code); void createProjectSslErrors(const QList<QSslError> & errors); void handleUpdateConnected(); void handleUpdateDisconnected(); void handleUpdateError(QAbstractSocket::SocketError error); void handleUpdateTextMessage(const QString & msg); void handleUpdateSslErrors(const QList<QSslError> & errors); // Member state public: PhoenixServicesClient *mClient; QNetworkAccessManager mManager; QUrl mUrl; SessionPtr mSession; QString mPhoenixPrefixPath; QString mUpdatesPath; // State for web sockets. We, unfortunately, have a lot of asynchronous // traffic I don't want to expose to clients. QSharedPointer<QWebSocket> mWebSocket; bool mUpdateConnected; bool mUpdateDisconnected; bool mUpdateFailure; unsigned int mRetryCount; unsigned int mRetryPause; friend class LogInFinished; }; class PhoenixServicesClient::LogInFinished : public QObject { Q_OBJECT public: LogInFinished(QObject *parent, PhoenixServicesClient::Impl & impl, QNetworkReply *reply, const QString & user) : QObject(parent), mImpl(impl), mReply(reply), mUser(user) { }; public slots: void finished() { mImpl.logInFinished(mReply, mUser); }; private: PhoenixServicesClient::Impl & mImpl; QNetworkReply *mReply; QString mUser; }; void PhoenixServicesClient::Impl::setBasicAuthFromSession( QNetworkRequestPtr request) { if (mClient->hasSession()) { QString userpass = QString("%1:%2").arg(mClient->session().user()) .arg(mClient->session().p4Ticket()); QString b64Userpass(userpass.toUtf8().toBase64()); QString value = QString("Basic %1").arg(b64Userpass); request->setRawHeader("Authorization", value.toUtf8()); } } void PhoenixServicesClient::Impl::logInFinished(QNetworkReply *reply, const QString & user) { if (reply->isFinished() && reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); RequestErrorPtr error = parseRequestError(data); SessionPtr session; if (!error) { QJsonDocument doc; QJsonParseError err; doc = doc.fromJson(data, &err); if (err.error == QJsonParseError::NoError) { QJsonObject object = doc.object(); if (object.contains("token") && object.contains("p4Ticket")) { QString token = object["token"].toString(); QString p4Ticket = object["p4Ticket"].toString(); session.reset(new Session); session->setUrl(mUrl); session->setUser(user); session->setToken(token); session->setP4Ticket(p4Ticket); mClient->setSession(*session); } } } if (!session) { QString msg = QString( "Unable to create session from JSON data: %1").arg( QString(data)); error.reset(new RequestError(msg, msg, RequestError::JSON_ERROR, RequestError::ERROR)); } emit mClient->logInDone(error, session); } } RequestErrorPtr PhoenixServicesClient::Impl::fromNetworkError( QNetworkReply::NetworkError code) { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); RequestErrorPtr error; if (code == QNetworkReply::AuthenticationRequiredError) { error.reset(new RequestError); QString msg("Authentication Required"); error->setBaseMessageText(msg); error->setMessageText(msg); error->setCode(RequestError::AUTHENTICATION_ERROR); error->setSeverity(RequestError::ERROR); } if (error.isNull() && reply->isReadable()) { // See if we have any kind of request error response QByteArray data = reply->readAll(); RequestErrorPtr e = parseRequestError(data); if (!e.isNull()) error = e; } if (error.isNull()) { error.reset(new RequestError); // There's not a lot of information here, beyond typical request headers QString msg = QString("Network Error %1").arg(code); error->setMessageText(msg); error->setBaseMessageText(msg); error->setCode(RequestError::NETWORK_ERROR); error->setSeverity(RequestError::ERROR); } return error; } RequestErrorPtr PhoenixServicesClient::Impl::fromSslErrors( const QList<QSslError> & errors) { RequestErrorPtr error(new RequestError()); // TODO convert the errors array to messages? error->setMessageText("SSL Error"); error->setBaseMessageText("SSL Error"); error->setCode(RequestError::SSL_ERROR); error->setSeverity(RequestError::ERROR); return error; } void PhoenixServicesClient::Impl::watch(const QList<QString> & projectIds) { QJsonDocument doc; QJsonObject obj; obj.insert("name", "watch"); obj.insert("token", mSession->token()); QJsonArray array; foreach(QJsonValue id, projectIds) { array.append(QJsonValue(id)); } obj.insert("projects", array); doc.setObject(obj); QByteArray json = doc.toJson(QJsonDocument::Compact); QString jsonUtf8 = QString::fromUtf8(json); mWebSocket->sendTextMessage(jsonUtf8); } void PhoenixServicesClient::Impl::unwatch(const QList<QString> & projectIds) { QJsonDocument doc; QJsonObject obj; obj.insert("name", "unwatch"); QJsonArray array; foreach(QJsonValue id, projectIds) { array.append(QJsonValue(id)); } obj.insert("projects", array); doc.setObject(obj); QByteArray json = doc.toJson(QJsonDocument::Compact); QString jsonUtf8 = QString::fromUtf8(json); mWebSocket->sendTextMessage(jsonUtf8); } void PhoenixServicesClient::Impl::setSession(const Session & session) { mSession.reset(new Session(session)); // TODO this triggers a Signal 11 at the moment. //connectWebSocket(); } void PhoenixServicesClient::Impl::connectWebSocket() { if (mWebSocket.isNull() == false) { disconnectWebSocket(); } mUpdateConnected = false; mUpdateDisconnected = false; mUpdateFailure = false; mWebSocket.reset(new QWebSocket()); connect(mWebSocket.data(), &QWebSocket::connected, this, &PhoenixServicesClient::Impl::handleUpdateConnected); connect(mWebSocket.data(), &QWebSocket::disconnected, this, &PhoenixServicesClient::Impl::handleUpdateDisconnected); connect(mWebSocket.data(), SLOT(error), this, SIGNAL(handleUpdateError)); connect(mWebSocket.data(), &QWebSocket::textMessageReceived, this, &PhoenixServicesClient::Impl::handleUpdateTextMessage); connect(mWebSocket.data(), &QWebSocket::sslErrors, this, &PhoenixServicesClient::Impl::handleUpdateSslErrors); mWebSocket->open(updateUrl()); waitForUpdateSocket(); } void PhoenixServicesClient::Impl::disconnectWebSocket() { if (mWebSocket.isNull() == false) { mWebSocket->close(); waitForUpdateSocket(); } } void PhoenixServicesClient::Impl::handleUpdateConnected() { mUpdateConnected = true; } void PhoenixServicesClient::Impl::handleUpdateDisconnected() { mUpdateDisconnected = true; } void PhoenixServicesClient::Impl::handleUpdateError( QAbstractSocket::SocketError error) { mUpdateFailure = true; RequestErrorPtr re(new RequestError); re->setCode(RequestError::WEB_SOCKET_ERROR); QString msg = QString("Socket error %1").arg(error); re->setMessageText(msg); re->setBaseMessageText(msg); re->setSeverity(3); mWebSocket.reset(NULL); emit mClient->updateError(re); } void PhoenixServicesClient::Impl::handleUpdateTextMessage( const QString & msg) { QJsonDocument doc; QJsonParseError err; doc.fromJson(msg.toUtf8(), &err); if (err.error != QJsonParseError::NoError) { RequestErrorPtr re(new RequestError); re->setCode(RequestError::JSON_ERROR); re->setSeverity(3); QString errmsg = QString("Failure handling update: %1").arg(msg); re->setBaseMessageText(errmsg); re->setMessageText(errmsg); emit mClient->updateError(re); } // The parse was ok, see if we have what we need QJsonObject object = doc.object(); QString name = object["name"].toString(); QJsonArray updates = object["updates"].toArray(); if (!name.isEmpty() && name == "status" && !updates.isEmpty()) { foreach(QJsonValue val, updates) { QJsonObject updateObj = val.toObject(); QSharedPointer<ProjectUpdate> update(new ProjectUpdate); update->projectId = updateObj["project"].toString(); update->change = updateObj["change"].toInt(); update->version = updateObj["version"].toInt(); emit mClient->projectUpdated(update); } } // Other messages may need to be dispatched if we ever want them, for // now, just ignore them. } void PhoenixServicesClient::Impl::handleUpdateSslErrors( const QList<QSslError> & errors) { mUpdateFailure = true; mWebSocket.reset(NULL); emit mClient->updateError(fromSslErrors(errors)); } void PhoenixServicesClient::Impl::waitForUpdateSocket() { for (unsigned int retries = 0; retries < mRetryCount && (mUpdateConnected || mUpdateFailure || mUpdateDisconnected); ++retries) { QThread::currentThread()->msleep(mRetryPause); } if ((mUpdateConnected || mUpdateFailure || mUpdateDisconnected) == false) { RequestErrorPtr error(new RequestError); error->setCode(RequestError::WEB_SOCKET_ERROR); QString msg = "Timeout attempting to connect"; error->setMessageText(msg); error->setBaseMessageText(msg); error->setSeverity(3); mWebSocket.reset(NULL); emit mClient->updateError(error); } } QUrl PhoenixServicesClient::Impl::updateUrl() { QUrl url(mUrl); QString path(mPhoenixPrefixPath); path += mUpdatesPath; url.setPath(path); return url; } void PhoenixServicesClient::Impl::handleLogInError( QNetworkReply::NetworkError code) { RequestErrorPtr error = fromNetworkError(code); emit mClient->logInDone(error, SessionPtr()); }; void PhoenixServicesClient::Impl::handleLogInSslErrors( const QList<QSslError> & errors) { RequestErrorPtr error = fromSslErrors(errors); emit mClient->logInDone(error, SessionPtr()); } void PhoenixServicesClient::Impl::fetchProjectsFinished() { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); PhoenixProjectListPtr projects; if (reply->isFinished() && reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); projects = phoenixProjectListFromJson(data); } RequestErrorPtr error; if (projects.isNull()) { QString msg = "JSON Parser Error"; error.reset( new RequestError(msg, msg, RequestError::JSON_ERROR, 3)); } emit mClient->fetchProjectsDone(error, projects); } void PhoenixServicesClient::Impl::fetchProjectsError( QNetworkReply::NetworkError code) { RequestErrorPtr error = fromNetworkError(code); emit mClient->fetchProjectsDone(error, QSharedPointer<QList<PhoenixProjectPtr> >()); } void PhoenixServicesClient::Impl::fetchProjectsSslErrors( const QList<QSslError> & errors) { RequestErrorPtr error = fromSslErrors(errors); emit mClient->fetchProjectsDone(error, QSharedPointer<QList<PhoenixProjectPtr> >()); } void PhoenixServicesClient::Impl::fetchProjectFinished() { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); PhoenixProjectPtr project; if (reply->isFinished() && reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); project = phoenixProjectFromJson(data); } RequestErrorPtr error; if (project.isNull()) { QString msg = "JSON Parser Error"; error.reset( new RequestError(msg, msg, RequestError::JSON_ERROR, 3)); } emit mClient->fetchProjectDone(error, project); } void PhoenixServicesClient::Impl::fetchProjectError( QNetworkReply::NetworkError code) { RequestErrorPtr error = fromNetworkError(code); emit mClient->fetchProjectDone(error, PhoenixProjectPtr()); } void PhoenixServicesClient::Impl::fetchProjectSslErrors( const QList<QSslError> & errors) { RequestErrorPtr error = fromSslErrors(errors); emit mClient->fetchProjectDone(error, PhoenixProjectPtr()); } void PhoenixServicesClient::Impl::createProjectFinished() { QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); PhoenixProjectPtr project; // Note that most errors should be handled by the fetchProjectError // handler. if (reply->isFinished() && reply->error() == QNetworkReply::NoError) { QByteArray data = reply->readAll(); qDebug() << "data from create project " << data; project = phoenixProjectFromJson(data); } RequestErrorPtr error; if (project.isNull()) { QString msg = "JSON Parser Error"; error.reset( new RequestError(msg, msg, RequestError::JSON_ERROR, 3)); } emit mClient->createProjectDone(error, project); } void PhoenixServicesClient::Impl::createProjectError( QNetworkReply::NetworkError code) { RequestErrorPtr error = fromNetworkError(code); emit mClient->createProjectDone(error, PhoenixProjectPtr()); } void PhoenixServicesClient::Impl::createProjectSslErrors( const QList<QSslError> & errors) { RequestErrorPtr error = fromSslErrors(errors); emit mClient->createProjectDone(error, PhoenixProjectPtr()); } PhoenixServicesClient::PhoenixServicesClient(QObject *parent) : QObject(parent), mImpl(new Impl(this)) { } PhoenixServicesClient::~PhoenixServicesClient() { delete mImpl; } void PhoenixServicesClient::setUrl(const QUrl & url) { mImpl->mUrl = url; } const QUrl & PhoenixServicesClient::url() const { return mImpl->mUrl; } bool PhoenixServicesClient::hasSession() const { return mImpl->mSession.isNull() == false; } const Session & PhoenixServicesClient::session() const { return *(mImpl->mSession); } void PhoenixServicesClient::setSession(const Session & session) { mImpl->setSession(session); } const QString & PhoenixServicesClient::phoenixPrefixPath() const { return mImpl->mPhoenixPrefixPath; } void PhoenixServicesClient::setPhoenixPrefixPath(const QString & path) { mImpl->mPhoenixPrefixPath = path; } const QString & PhoenixServicesClient::updatesPath() const { return mImpl->mUpdatesPath; } void PhoenixServicesClient::setUpdatesPath(const QString & path) { mImpl->mUpdatesPath = path; } void PhoenixServicesClient::logIn(const QString & user, const QString & password) { QNetworkRequestPtr request = mImpl->createRequest(); // set the right url... mImpl->setRequestUrlWithPath(request, "/sessions"); QByteArray data = mImpl->createSessionPostBody(user, password); request->setRawHeader("Content-Length", QByteArray::number(data.size())); QNetworkReply *reply = mImpl->mManager.post(*request, data); LogInFinished *finisher = new LogInFinished(this, *mImpl, reply, user); connect(reply, SIGNAL(finished()), finisher, SLOT(finished())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), mImpl, SLOT(handleLogInError(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors( const QList<QSslError> &)), mImpl, SLOT(handleLogInSslErrors( const QList<QSslError> &))); } void PhoenixServicesClient::fetchProjects() { QNetworkRequestPtr request = mImpl->createRequest(); mImpl->setRequestUrlWithPath(request, "/projects"); mImpl->setBasicAuthFromSession(request); QNetworkReply *reply = mImpl->mManager.get(*request); connect(reply, SIGNAL(finished()), mImpl, SLOT(fetchProjectsFinished())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), mImpl, SLOT(fetchProjectsError(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors( const QList<QSslError> &)), mImpl, SLOT(fetchProjectsSslErrors( const QList<QSslError> &))); } void PhoenixServicesClient::fetchProject(const QString & id) { QNetworkRequestPtr request = mImpl->createRequest(); // setRequestUrlWithPath will pass this on to a URL, which will handle // appropriate path encoding. QString path = QString("/projects/%1").arg(id); mImpl->setRequestUrlWithPath(request, path); mImpl->setBasicAuthFromSession(request); QNetworkReply *reply = mImpl->mManager.get(*request); connect(reply, SIGNAL(finished()), mImpl, SLOT(fetchProjectFinished())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), mImpl, SLOT(fetchProjectError(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors( const QList<QSslError> &)), mImpl, SLOT(fetchProjectSslErrors( const QList<QSslError> &))); } void PhoenixServicesClient::createProject(const PhoenixProject & project) { QNetworkRequestPtr request = mImpl->createRequest(); mImpl->setRequestUrlWithPath(request, "/projects"); mImpl->setBasicAuthFromSession(request); QByteArray data = project.project() .document() .toJson(QJsonDocument::Compact); QNetworkReply *reply = mImpl->mManager.post(*request, data); connect(reply, SIGNAL(finished()), mImpl, SLOT(createProjectFinished())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), mImpl, SLOT(createProjectError(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors( const QList<QSslError> &)), mImpl, SLOT(createProjectSslErrors( const QList<QSslError> &))); } void PhoenixServicesClient::watchProject(const QString & projectId) { QList<QString> ids; ids.append(projectId); mImpl->watch(ids); } void PhoenixServicesClient::watchProjects(const QList<QString> & projectIds) { mImpl->watch(projectIds); } void PhoenixServicesClient::unwatchProjects( const QList<QString> & projectIds) { mImpl->unwatch(projectIds); } void PhoenixServicesClient::unwatchProject(const QString & projectId) { QList<QString> ids; ids.append(projectId); mImpl->unwatch(ids); } } #include "PhoenixServicesClient.moc"
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#18 | 14025 | tjuricek |
Revise Qt SDK to a single 'helix_web_services_client' project. Most references to "Phoenix" have now been removed. Additionally, this is more similar to the other platform client SDKs in Ruby and JavaScript. Documentation via Doxygen is now available, and will be how much of the SDK reference should occur. |
||
#17 | 13941 | tjuricek |
Re-implemented the sync project methods at the HTTP level. The Qt API is missing the "members" concept, but it's likely not quite usable just yet. It's existing logic does work, however. |
||
#16 | 13532 | tjuricek |
Qt SDK: Add constructor that uses an application's QSettings for caching Sessions for each URL Added a simple validateSession remote call to ping the services instance to see if the session is indeed usable. Also, removing puma configuraiton that is automatically generated in the (shared) development instance. |
||
#15 | 13530 | tjuricek |
Add p4_phoenix_services package and Salt configuration for deployment. This uncovered a couple of issues from the C++ API during it's conversion to C++03. So, in a nutshell, most operations, except for notifications, appear to be working (well, using Vagrant machines). |
||
#14 | 13510 | tjuricek |
Convert version information to macros to get around unused variable warnings that some people want to use to fail builds. Also, fixed an actual reorder issue, and enabled '-Wall' on the cmake config. |
||
#13 | 13508 | tjuricek | Replace use of C++11 'nullptr' with NULL | ||
#12 | 13506 | tjuricek |
Change to a C++03 build. Major changes: 1. QSharedPointer::create(...) is much more restricted than in C++11, so just use the .reset() method unless you're passing in a single const reference argument to the constructor. 2. Using Qt's foreach. 3. Replace lambdas with simpler helper methods. This seems to work, but we may have subtle memory issues I'm not 100% on top of yet. |
||
#11 | 13497 | tjuricek | Follow QObject memory management conventions for the PhoenixServicesClient. | ||
#10 | 13471 | tjuricek |
Define some JSON messages for Qt API's websocket interaction. Not tested... yet. |
||
#9 | 13470 | tjuricek |
Phoenix notification services, client API, including new phoenix_updater This is an interim commit containing a first pass implementation of the phoenix_updater. Notably missing parts: - The Qt API doesn't yet actually interact with the phoenix_updater - The phoenix_services web service doesn't filter out notifications I *may* end up creating another web application *just* to filter out notifications, since this may end up taking up a lot of background workers. |
||
#8 | 13460 | tjuricek |
Call out authentication problems with a specific application error code. This allows Qt clients to easily know when they should recreate a new session. |
||
#7 | 13459 | tjuricek |
Return the created project when creating a new project, since default values will often be filled out. Allow new projects to be created only with names set. We'll generate an ID at the moment, when I have better indexing, I'll double check for uniqueness. |
||
#6 | 13455 | tjuricek | Basic Phoenix project metadata (the project name) can now be created and read back. | ||
#5 | 13454 | tjuricek |
First cut at SDK implementation of the Create-Read lifecycle of Phoenix projects. (Bugs on the server side may be the issue, we'll see. TBD.) |
||
#4 | 13452 | tjuricek | Normalize header includes and preliminary implementation of the Project-related methods of the PhoenixServicesClient. | ||
#3 | 13451 | tjuricek | Setup common error handling callbacks for most of the first operations. | ||
#2 | 13449 | tjuricek | Adjusting the User-Agent string which gets rejected by Unicorn. | ||
#1 | 13443 | tjuricek |
Reorganized the Qt libraries into a separate part of the tree, to make it easier for CMake configuration. Added 'qt_build' and 'qt_test' tasks to at least execute tests and fail the build if they don't pass. Started the implementation of the project library interaction. Change: 1018651 Date: 3/4/15 11:43 AM Client: tjuricek_dhcp-141-n100_5959 User: tjuricek Status: pending Type: public Description: Reorganized the Qt libraries into a separate part of the tree, to make it easier for CMake configuration. Added 'qt_build' and 'qt_test' tasks to at least execute tests and fail the build if they don't pass. Started the implementation of the project library interaction. JobStatus: Jobs: Files: //web-services/p4ws-main/Rakefile //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/CMakeLists.txt //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/PhoenixIntegrationTests.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/README //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/PhoenixProject.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/PhoenixProject.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/PhoenixServicesClient.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/PhoenixServicesClient.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/RequestError.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/RequestError.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/Session.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/phoenix/Session.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/test/PhoenixServicesClientTests.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/test/PhoenixServicesClientTests.h //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/test/SessionTests.cpp //web-services/p4ws-main/p4_phoenix_services/clients/qt/p4_phoenix_services_client/test/SessionTests.h //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/CMakeLists.txt //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services.h //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/Branch.cpp //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/Branch.h //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/Project.cpp //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/Project.h //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/View.cpp //web-services/p4ws-main/p4_project_services/clients/qt/p4_project_services_client/p4_project_services/View.h //web-services/p4ws-main/qt/CMakeLists.txt //web-services/p4ws-main/qt/p4_phoenix_services_client/CMakeLists.txt //web-services/p4ws-main/qt/p4_phoenix_services_client/PhoenixIntegrationTests.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/README //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix.h //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/PhoenixProject.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/PhoenixProject.h //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/PhoenixServicesClient.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/PhoenixServicesClient.h //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/RequestError.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/RequestError.h //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/Session.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/phoenix/Session.h //web-services/p4ws-main/qt/p4_phoenix_services_client/test/PhoenixServicesClientTests.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/test/PhoenixServicesClientTests.h //web-services/p4ws-main/qt/p4_phoenix_services_client/test/SessionTests.cpp //web-services/p4ws-main/qt/p4_phoenix_services_client/test/SessionTests.h //web-services/p4ws-main/qt/p4_project_services_client/CMakeLists.txt //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeCache.txt //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CMakeCCompiler.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CMakeCXXCompiler.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CMakeDetermineCompilerABI_C.bin //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CMakeDetermineCompilerABI_CXX.bin //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CMakeSystem.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CompilerIdC/CMakeCCompilerId.c //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CompilerIdC/a.out //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CompilerIdCXX/CMakeCXXCompilerId.cpp //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/2.8.12/CompilerIdCXX/a.out //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/CMakeDirectoryInformation.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/CMakeOutput.log //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/Makefile.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/Makefile2 //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/TargetDirectories.txt //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/cmake.check_cache //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/DependInfo.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/build.make //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/cmake_clean.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/cmake_clean_target.cmake //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/depend.make //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/flags.make //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/link.txt //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/p4_project_services_client.dir/progress.make //web-services/p4ws-main/qt/p4_project_services_client/build/CMakeFiles/progress.marks //web-services/p4ws-main/qt/p4_project_services_client/build/Makefile //web-services/p4ws-main/qt/p4_project_services_client/build/cmake_install.cmake //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services.h //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/Branch.cpp //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/Branch.h //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/Project.cpp //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/Project.h //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/View.cpp //web-services/p4ws-main/qt/p4_project_services_client/p4_project_services/View.h |