Return-Path: X-Original-To: apmail-cordova-commits-archive@www.apache.org Delivered-To: apmail-cordova-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 90E78FE7B for ; Tue, 7 May 2013 15:13:53 +0000 (UTC) Received: (qmail 73982 invoked by uid 500); 7 May 2013 15:13:51 -0000 Delivered-To: apmail-cordova-commits-archive@cordova.apache.org Received: (qmail 73926 invoked by uid 500); 7 May 2013 15:13:51 -0000 Mailing-List: contact commits-help@cordova.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cordova.apache.org Delivered-To: mailing list commits@cordova.apache.org Received: (qmail 72691 invoked by uid 99); 7 May 2013 15:13:50 -0000 Received: from tyr.zones.apache.org (HELO tyr.zones.apache.org) (140.211.11.114) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 07 May 2013 15:13:50 +0000 Received: by tyr.zones.apache.org (Postfix, from userid 65534) id 066138887C5; Tue, 7 May 2013 15:13:50 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: lorinbeer@apache.org To: commits@cordova.apache.org Date: Tue, 07 May 2013 15:14:11 -0000 Message-Id: <3ba0c9acefe14599ada16cbeac096452@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [24/50] [abbrv] Fix JPPS and Utils plugins directory structure http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.cpp b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.cpp new file mode 100644 index 0000000..83616b8 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.cpp @@ -0,0 +1,355 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +#include "PPSInterfaceGlue.h" + +#include +#include +#include + +#include +#include + +#include + +#include "../core/PPSEvent.h" + +namespace jpps { + +const std::string PPSInterfaceGlue::EVENT_OPEN = "ppsOpened"; +const std::string PPSInterfaceGlue::EVENT_OPEN_FAILED = "ppsOpenFailed"; +const std::string PPSInterfaceGlue::EVENT_FIRST_READ = "ppsFirstRead"; +const std::string PPSInterfaceGlue::EVENT_NEW_DATA = "OnChange";//"ppsNewData"; +const std::string PPSInterfaceGlue::EVENT_CLOSE = "ppsClosed"; +const std::string PPSInterfaceGlue::EVENT_WRITE_FAILED = "ppsWriteFailed"; +const std::string PPSInterfaceGlue::EVENT_READ_FAILED = "ppsReadFailed"; + +const std::string PPSInterfaceGlue::ENCODING_N = "n"; +const std::string PPSInterfaceGlue::ENCODING_B = "b"; +const std::string PPSInterfaceGlue::ENCODING_JSON = "json"; + +const Json::StaticString PPSInterfaceGlue::JSON_REMOVE("remove"); +const Json::StaticString PPSInterfaceGlue::JSON_CHANGED("changed"); +const Json::StaticString PPSInterfaceGlue::JSON_DATA("data"); +const Json::StaticString PPSInterfaceGlue::JSON_OBJNAME("objName"); +const Json::StaticString PPSInterfaceGlue::JSON_CHANGE_DATA("changeData"); +const Json::StaticString PPSInterfaceGlue::JSON_ALL_DATA("allData"); + + +PPSInterfaceGlue::PPSInterfaceGlue() +: m_interface() +, m_pArg(NULL) +, m_handleOpen(NULL) +, m_handleFirstRead(NULL) +, m_handleNewData(NULL) +, m_handleClose(NULL) +, m_handleOpenFailed(NULL) +, m_handleWriteFailed(NULL) +, m_handleReadFailed(NULL) +{ + m_interface.setEventFunc(onEvent, this); +} + +PPSInterfaceGlue::~PPSInterfaceGlue() +{ + m_interface.setEventFunc(NULL); +} + +void PPSInterfaceGlue::callbackInit(void* pArg, + callback* handleOpen, + callback* handleFirstRead, + callback* handleNewData, + callback* handleClose, + callback* handleOpenFailed, + callback* handleWriteFailed, + callback* handleReadFailed) +{ + m_pArg = pArg; + m_handleOpen = handleOpen; + m_handleFirstRead = handleFirstRead; + m_handleNewData = handleNewData; + m_handleClose = handleClose; + m_handleOpenFailed = handleOpenFailed; + m_handleWriteFailed = handleWriteFailed; + m_handleReadFailed = handleReadFailed; +} + +void PPSInterfaceGlue::setVerbose(unsigned short v) +{ + m_interface.setVerbose(v); +} + +bool PPSInterfaceGlue::open(const std::string& path, int oflags) +{ + // We don't expose the "mode" to the JS layer - always create in 0666 mode + return m_interface.open(path, oflags, 0666, false); +} + +void PPSInterfaceGlue::close() +{ + m_interface.close(); +} + +void PPSInterfaceGlue::sync() +{ + m_interface.sync(); +} + +void PPSInterfaceGlue::onEvent(void* pArg, const PPSEvent& event) +{ + PPSInterfaceGlue* pGlue = static_cast(pArg); + + if (pGlue != NULL) + pGlue->onEvent(event); +} + +void PPSInterfaceGlue::onEvent(const PPSEvent& event) +{ + callback* pFunc = NULL; + std::string sArg; + + switch (event.getEventType()) { + + case PPSEvent::PPS_EVENT_OPENED: + pFunc = m_handleOpen; + sArg = EVENT_OPEN; + break; + + case PPSEvent::PPS_EVENT_FIRST_READ_COMPLETE: + pFunc = m_handleFirstRead; + sArg = EVENT_FIRST_READ + " " + handleNewData(event.getNewData()); + break; + + case PPSEvent::PPS_EVENT_NEW_DATA: + pFunc = m_handleNewData; + sArg = EVENT_NEW_DATA + " " + handleNewData(event.getNewData()); + break; + + case PPSEvent::PPS_EVENT_CLOSED: + pFunc = m_handleClose; + sArg = EVENT_CLOSE; + break; + + case PPSEvent::PPS_EVENT_OPEN_FAILED: + pFunc = m_handleOpenFailed; + sArg = EVENT_OPEN_FAILED + " " + event.getMessage(); + break; + + case PPSEvent::PPS_EVENT_WRITE_FAILED: + pFunc = m_handleWriteFailed; + sArg = EVENT_WRITE_FAILED + " " + event.getMessage(); + break; + + case PPSEvent::PPS_EVENT_READ_FAILED: + pFunc = m_handleReadFailed; + sArg = EVENT_READ_FAILED + " " + event.getMessage(); + break; + } + + if (pFunc != NULL) + pFunc(m_pArg, sArg); +} + +std::string PPSInterfaceGlue::handleNewData(const ppsObject& newData) +{ + Json::Value data(Json::nullValue); + data[JSON_CHANGE_DATA] = JSONEncodeNewData(newData); + data[JSON_ALL_DATA] = JSONEncodeRead(m_interface.read()); + + Json::FastWriter writer; + return writer.write(data); +} + +std::string PPSInterfaceGlue::read() const +{ + Json::Value data = JSONEncodeRead(m_interface.read()); + Json::FastWriter writer; + return writer.write(data); +} + +Json::Value PPSInterfaceGlue::JSONEncodeRead(const ppsObject& ppsObj) const +{ + // If the ppsObj is empty, we can't encode it + if (ppsObj.name.empty()) + return ""; + + Json::Value readData(Json::nullValue); + + for (const_ppsAttrIter it = ppsObj.attributes.begin(); it != ppsObj.attributes.end(); it++) { + + ppsAttribute ppsAttrib = (*it).second; + + // An attribute was deleted: update the JSON data structure and the event data + if (ppsAttrib.flags & PPS_DELETED) { + + readData.removeMember(ppsAttrib.name); + } + else { + + // The value is a number + if (ppsAttrib.encoding == ENCODING_N) { + + // Convert the value to floating point + // istringstream is locale aware - we shouldn't need to perform any special + // processing in order to properly convert the data to a floating point + // TODO: test that the istringstream conversion works with a locale + // that uses alternate floating point number encoding + std::istringstream stream(ppsAttrib.value); + double doubleValue; + + // Try to convert the value to a floating point + if (!(stream >> doubleValue)) { + + std::string err = EVENT_READ_FAILED + " Failed to convert the string \"" + ppsAttrib.value + "\" to a real number."; + m_handleReadFailed(m_pArg, err); + return ""; + } + + readData[ppsAttrib.name] = doubleValue; + } + // The value is a boolean + else if (ppsAttrib.encoding == ENCODING_B) { + + readData[ppsAttrib.name] = (ppsAttrib.value == "true"); + } + // The value is JSON data + else if (ppsAttrib.encoding == ENCODING_JSON) { + + Json::Reader reader; + reader.parse(ppsAttrib.value, readData[ppsAttrib.name]); + } + // Just pass the value through as a straight string + else { + + readData[ppsAttrib.name] = ppsAttrib.value; + } + } + } + + return readData; +} + +Json::Value PPSInterfaceGlue::JSONEncodeNewData(const ppsObject& ppsObj) const +{ + // If the ppsObj is empty, we can't encode it + if (ppsObj.name.empty()) + return ""; + + Json::Value eventData(Json::nullValue); + + // Set the PPS object name + eventData[JSON_OBJNAME] = ppsObj.name.substr(1); // PR 159829 : Remove the pre-pending '@' symbol + + for (const_ppsAttrIter it = ppsObj.attributes.begin(); it != ppsObj.attributes.end(); it++) { + + ppsAttribute ppsAttrib = (*it).second; + + // An attribute was deleted: update the JSON data structure and the event data + if (ppsAttrib.flags & PPS_DELETED) { + + eventData[JSON_REMOVE][ppsAttrib.name] = true; + } + else { + + eventData[JSON_CHANGED][ppsAttrib.name] = true; + + // The value is a number + if (ppsAttrib.encoding == ENCODING_N) { + + // Convert the value to floating point + // istringstream is locale aware - we shouldn't need to perform any special + // processing in order to properly convert the data to a floating point + // TODO: test that the istringstream conversion works with a locale + // that uses alternate floating point number encoding + std::istringstream stream(ppsAttrib.value); + double doubleValue; + + // Try to convert the value to a floating point + if (!(stream >> doubleValue)) { + + std::string err = EVENT_READ_FAILED + " Failed to convert the string \"" + ppsAttrib.value + "\" to a real number."; + m_handleReadFailed(m_pArg, err); + return ""; + } + + eventData[JSON_DATA][ppsAttrib.name] = doubleValue; + } + // The value is a boolean + else if (ppsAttrib.encoding == ENCODING_B) { + + eventData[JSON_DATA][ppsAttrib.name] = (ppsAttrib.value == "true"); + } + // The value is JSON data + else if (ppsAttrib.encoding == ENCODING_JSON) { + + Json::Reader reader; + reader.parse(ppsAttrib.value, eventData[JSON_DATA][ppsAttrib.name]); + } + // Just pass the value through as a straight string + else { + + eventData[JSON_DATA][ppsAttrib.name] = ppsAttrib.value; + } + } + } + + return eventData; +} + +void PPSInterfaceGlue::write(const std::string& data) +{ + Json::Reader reader; + Json::Value root; + + bool parsingSuccessful = reader.parse(data, root); + + // If parsing the JSON string fails, return a write error + if (!parsingSuccessful) { + + std::string err = EVENT_WRITE_FAILED + " JSON failed to parse the string (\"" + data + "\") to be written. (" + reader.getFormatedErrorMessages() + ")"; + m_handleWriteFailed(m_pArg, err); + return; + } + + Json::Value::Members memberNames = root.getMemberNames(); + + std::ostringstream output; + output.precision(15); + + Json::Value member; + + for (unsigned int i = 0; i < memberNames.size(); i++) { + + output << memberNames[i] << ":"; + member = root[memberNames[i]]; + + if (member.isObject() || member.isArray()) { + + Json::FastWriter writer; + output << ENCODING_JSON << ":" << writer.write(member); // write() adds an \n + } + else if (member.isBool()) { + + output << ENCODING_B << ":" << member.asString() << std::endl; + } + else if (member.isNumeric()) { + + output << ENCODING_N << ":" << member.asDouble() << std::endl; + } + else if (member.isString()) { + + output << ":" << member.asString() << std::endl; + } + else { + + std::string err = EVENT_WRITE_FAILED + " The string passed in (\"" + data + "\") contains an invalid JSON type."; + m_handleWriteFailed(m_pArg, err); + return; + } + } + + m_interface.write(output.str()); +} + +} /* namespace jpps */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.h b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.h new file mode 100644 index 0000000..fafbacd --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSInterfaceGlue.h @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#ifndef PPSINTERFACEGLUE_H_ +#define PPSINTERFACEGLUE_H_ + +#include "../core/PPSInterface.h" +#include "PluginTypes.h" + +#include + +#include + +namespace jpps { +class PPSEvent; +struct ppsObject; +} + +namespace jpps { + +/** + * This class bridges JavaScript and the native PPSInterface code. + */ +class PPSInterfaceGlue { + +public: + + /** + * Constructor. + */ + PPSInterfaceGlue(); + + /** + * Destructor. + */ + virtual ~PPSInterfaceGlue(); + + /** + * The browser plugin should set these handlers. + * + * @param pArg pArg will be passed back to each callback function when it is called. + */ + void callbackInit(void* pArg, + callback* handleOpen, + callback* handleFirstRead, + callback* handleNewData, + callback* handleClose, + callback* handleOpenFailed, + callback* handleWriteFailed, + callback* handleReadFailed); + + /** + * Set the verbosity of logging to the slog. + */ + void setVerbose(unsigned short v); + + /** + * Open a PPS object. + */ + bool open(const std::string& path, int oflags); + + /** + * Write to a PPS object. + */ + void write(const std::string& data); + + /** + * Read from the PPS object. This actually returns the cached value of the last + * onNewData event from PPSInteraface, then encodes it as JSON. + */ + std::string read() const; + + /** + * Close this PPS object. + */ + void close(); + + /** + * Forces all queued I/O operations for this object to finish, synchronizing the file's state. + * The function blocks until this is finished. + */ + void sync(); + + /** + * The function that the PPSInterface will call when an event happens. + * This is the static function that is used as a function pointer for + * PPSInterface::setEventFunc(). + * + * @param event The event PPSInterface is sending. + * @param pArg A pointer to a PPSInterfaceGlue object, passed in during + * object construction. + */ + static void onEvent(void* pArg, const PPSEvent& event); + +private: + + /** + * The static PPSInterfaceGlue::onEvent() calls this onEvent to do the actual work. + */ + void onEvent(const PPSEvent& event); + + /** + * Handle a new data event. + */ + std::string handleNewData(const ppsObject& newData); + + /** + * Take a ppsObject and turn it into a JSON string to send back to the JavaScript + * with a new data event. This structures the JSON with changed properties and the + * data that has changed. + */ + Json::Value JSONEncodeNewData(const ppsObject& ppsObj) const; + + /** + * Take a ppsObject and turn it into a JSON string to send back to the JavaScript + * when a call to read() is made. + */ + Json::Value JSONEncodeRead(const ppsObject& ppsObj) const; + + // String names for the various events + static const std::string EVENT_OPEN; + static const std::string EVENT_OPEN_FAILED; + static const std::string EVENT_FIRST_READ; + static const std::string EVENT_NEW_DATA; + static const std::string EVENT_CLOSE; + static const std::string EVENT_READ_FAILED; + static const std::string EVENT_WRITE_FAILED; + + /** Custom PPS encoding value: an "n" means a real number. */ + static const std::string ENCODING_N; + /** Custom PPS encoding value: a "b" means a boolean value. */ + static const std::string ENCODING_B; + /** Custom PPS encoding value: the data is encoded using JSON. */ + static const std::string ENCODING_JSON; + + // JSON constants + static const Json::StaticString JSON_REMOVE; + static const Json::StaticString JSON_CHANGED; + static const Json::StaticString JSON_DATA; + static const Json::StaticString JSON_OBJNAME; + static const Json::StaticString JSON_CHANGE_DATA; + static const Json::StaticString JSON_ALL_DATA; + + /** The interface this object wraps. */ + PPSInterface m_interface; + + // Handlers for various events + void* m_pArg; + callback* m_handleOpen; + callback* m_handleFirstRead; + callback* m_handleNewData; + callback* m_handleClose; + callback* m_handleOpenFailed; + callback* m_handleWriteFailed; + callback* m_handleReadFailed; +}; + +} /* namespace jpps */ +#endif /* PPSINTERFACEGLUE_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.cpp b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.cpp new file mode 100644 index 0000000..2eb4552 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.cpp @@ -0,0 +1,300 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +#include "PPSServerGlue.h" + +#include +#include +#include + +#include + +#include +#include + +namespace jpps { + +const std::string PPSServerGlue::EVENT_OPEN = "onOpen"; +const std::string PPSServerGlue::EVENT_CLOSE = "onClose"; +const std::string PPSServerGlue::EVENT_CLIENT_CONNECT = "onClientConnect"; +const std::string PPSServerGlue::EVENT_CLIENT_DISCONNECT = "onClientDisconnect"; +const std::string PPSServerGlue::EVENT_MESSAGE = "onMessage"; +const std::string PPSServerGlue::EVENT_OPEN_FAILED = "onOpenFailed"; +const std::string PPSServerGlue::EVENT_SEND_MESSAGE_FAILED = "onSendMessageFailed"; +const std::string PPSServerGlue::EVENT_RECEIVE_MESSAGE_FAILED = "onReceiveMessageFailed"; + +const std::string PPSServerGlue::ENCODING_N = "n"; +const std::string PPSServerGlue::ENCODING_B = "b"; +const std::string PPSServerGlue::ENCODING_JSON = "json"; + +const Json::StaticString PPSServerGlue::JSON_DATA("data"); +const Json::StaticString PPSServerGlue::JSON_CONNECTION_ID("clientId"); + +PPSServerGlue::PPSServerGlue() +: m_interface() +, m_pArg(NULL) +, m_handleOpen(NULL) +, m_handleClose(NULL) +, m_handleClientConnect(NULL) +, m_handleClientDisconnect(NULL) +, m_handleMessage(NULL) +, m_handleOpenFailed(NULL) +, m_handleSendMessageFailed(NULL) +, m_handleReceiveMessageFailed(NULL) +{ + m_interface.setEventFunc(onEvent, this); +} + +PPSServerGlue::~PPSServerGlue() +{ + m_interface.setEventFunc(NULL); +} + +void PPSServerGlue::callbackInit(void* pArg, + callback* handleOpen, + callback* handleClose, + callback* handleClientConnect, + callback* handleClientDisconnect, + callback* handleMessage, + callback* handleOpenFailed, + callback* handleSendMessageFailed, + callback* handleReceiveMessageFailed) +{ + m_pArg = pArg; + m_handleOpen = handleOpen; + m_handleClose = handleClose; + m_handleClientConnect = handleClientConnect; + m_handleClientDisconnect = handleClientDisconnect; + m_handleMessage = handleMessage; + m_handleOpenFailed = handleOpenFailed; + m_handleSendMessageFailed = handleSendMessageFailed; + m_handleReceiveMessageFailed = handleReceiveMessageFailed; +} + + +void PPSServerGlue::setVerbose(unsigned short v) +{ + m_interface.setVerbose(v); +} + +bool PPSServerGlue::open(const std::string& path, int oflags) +{ + // Make sure we're creating the server, if it doesn't exist + if (!(oflags & O_CREAT)) + oflags &= O_CREAT; + + // We don't expose the "mode" to the JS layer - always create in 0666 mode + return m_interface.open(path, oflags, 0666, true); +} + +void PPSServerGlue::close() +{ + m_interface.close(); +} + +void PPSServerGlue::sendMessage(const std::string& clientID, const std::string& msg) +{ + std::string decodedMsg = JSONDecodeData(msg); + std::string message(clientID + "\n" + decodedMsg); + m_interface.write(message); +} + +void PPSServerGlue::broadcastMessage(const std::string& msg) +{ + m_interface.write(JSONDecodeData(msg)); +} + +void PPSServerGlue::onEvent(void* pArg, const PPSEvent& event) +{ + PPSServerGlue* pGlue = static_cast(pArg); + + if (pGlue != NULL) + pGlue->onEvent(event); +} + +void PPSServerGlue::onEvent(const PPSEvent& event) +{ + callback* pFunc = NULL; + std::string sArg; + + switch (event.getEventType()) { + + case PPSEvent::PPS_EVENT_OPENED: + pFunc = m_handleOpen; + sArg = EVENT_OPEN; + break; + + // The server doesn't do anything with this event + case PPSEvent::PPS_EVENT_FIRST_READ_COMPLETE: + break; + + case PPSEvent::PPS_EVENT_NEW_DATA: + { + ppsObject data(event.getNewData()); + + // This means a new connection + if (data.flags & PPS_CREATED) { + sArg = EVENT_CLIENT_CONNECT; + pFunc = m_handleClientConnect; + } + // This means a connection is closed + else if (data.flags & PPS_DELETED) { + sArg = EVENT_CLIENT_DISCONNECT; + pFunc = m_handleClientDisconnect; + } + // We're getting data from the connection + else { + sArg = EVENT_MESSAGE; + pFunc = m_handleMessage; + } + + sArg += " " + JSONEncodeData(data); + + break; + } + + case PPSEvent::PPS_EVENT_CLOSED: + pFunc = m_handleClose; + sArg = EVENT_CLOSE; + break; + + case PPSEvent::PPS_EVENT_OPEN_FAILED: + pFunc = m_handleOpenFailed; + sArg = EVENT_OPEN_FAILED + " " + event.getMessage(); + break; + + case PPSEvent::PPS_EVENT_WRITE_FAILED: + pFunc = m_handleSendMessageFailed; + sArg = EVENT_SEND_MESSAGE_FAILED + " " + event.getMessage(); + break; + + case PPSEvent::PPS_EVENT_READ_FAILED: + pFunc = m_handleReceiveMessageFailed; + sArg = EVENT_RECEIVE_MESSAGE_FAILED + event.getMessage(); + break; + } + + if (pFunc != NULL) + pFunc(m_pArg, sArg); + +} + +std::string PPSServerGlue::JSONEncodeData(const ppsObject& ppsObj) const +{ + // If the ppsObj is empty, we can't encode it + if (ppsObj.name.empty()) + return ""; + + Json::Value eventData(Json::nullValue); + + // Set the client id + // Chop off the '+' or '-' if it's there + eventData[JSON_CONNECTION_ID] = ppsObj.name; + + for (const_ppsAttrIter it = ppsObj.attributes.begin(); it != ppsObj.attributes.end(); it++) { + + ppsAttribute ppsAttrib = (*it).second; + + // The value is a number + if (ppsAttrib.encoding == ENCODING_N) { + + // Convert the value to floating point + // istringstream is locale aware - we shouldn't need to perform any special + // processing in order to properly convert the data to a floating point + // TODO: test that the istringstream conversion works with a locale + // that uses alternate floating point number encoding + std::istringstream stream(ppsAttrib.value); + double doubleValue; + + // Try to convert the value to a floating point + if (!(stream >> doubleValue)) { + + std::string err = EVENT_RECEIVE_MESSAGE_FAILED + " Failed to convert the string \"" + ppsAttrib.value + "\" to a real number."; + m_handleReceiveMessageFailed(m_pArg, err); + return ""; + } + + eventData[JSON_DATA][ppsAttrib.name] = doubleValue; + } + // The value is a boolean + else if (ppsAttrib.encoding == ENCODING_B) { + + eventData[JSON_DATA][ppsAttrib.name] = (ppsAttrib.value == "true"); + } + // The value is JSON data + else if (ppsAttrib.encoding == ENCODING_JSON) { + + Json::Reader reader; + reader.parse(ppsAttrib.value, eventData[JSON_DATA][ppsAttrib.name]); + } + // Just pass the value through as a straight string + else { + + eventData[JSON_DATA][ppsAttrib.name] = ppsAttrib.value; + } + } + + Json::FastWriter writer; + return writer.write(eventData); +} + +std::string PPSServerGlue::JSONDecodeData(const std::string& data) const +{ + Json::Reader reader; + Json::Value root; + + bool parsingSuccessful = reader.parse(data, root); + + // If parsing the JSON string fails, return a write error + if (!parsingSuccessful) { + + std::string err = EVENT_SEND_MESSAGE_FAILED + " JSON failed to parse the string (\"" + data + "\") to be written. (" + reader.getFormatedErrorMessages() + ")"; + m_handleSendMessageFailed(m_pArg, err); + return ""; + } + + Json::Value::Members memberNames = root.getMemberNames(); + + std::ostringstream output; + output.precision(15); + + Json::Value member; + + for (unsigned int i = 0; i < memberNames.size(); i++) { + + output << memberNames[i] << ":"; + member = root[memberNames[i]]; + + if (member.isObject() || member.isArray()) { + + Json::FastWriter writer; + output << ENCODING_JSON << ":" << writer.write(member); + } + else if (member.isBool()) { + + output << ENCODING_B << ":" << member.asString(); + } + else if (member.isNumeric()) { + + output << ENCODING_N << ":" << member.asDouble(); + } + else if (member.isString()) { + + output << ":" << member.asString(); + } + else { + + std::string err = EVENT_SEND_MESSAGE_FAILED + " The string passed in (\"" + data + "\") contains an invalid JSON type."; + m_handleSendMessageFailed(m_pArg, err); + return ""; + } + + // Make sure we terminate the line + output << std::endl; + } + + return output.str(); +} + +} /* namespace jpps */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.h b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.h new file mode 100644 index 0000000..8891829 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PPSServerGlue.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#ifndef PPSSERVERGLUE_H_ +#define PPSSERVERGLUE_H_ + +#include "../core/PPSInterface.h" +#include "PluginTypes.h" + +// Forward declaration +namespace Json { +class StaticString; +} +namespace jpps { +class PPSEvent; +struct ppsObject; +} + +namespace jpps { + +/** + * Act as glue between jpps Server class an the PPSInterface. + * This class encapsulates a PPS object as a PPS server. + * TODO: write a better comment + */ +class PPSServerGlue { + +public: + + /** + * Constructor. + */ + PPSServerGlue(); + + /** + * Destructor. + */ + virtual ~PPSServerGlue(); + + /** + * The browser plugin should set these handlers. + * + * @param pArg pArg will be passed back to each callback function when it is called. + */ + void callbackInit(void* pArg, + callback* handleOpen, + callback* handleClose, + callback* handleClientConnect, + callback* handleClientDisconnect, + callback* handleMessage, + callback* handleOpenFailed, + callback* handleSendMessageFailed, + callback* handleReceiveMessageFailed); + + /** + * Set the verbosity of logging to the slog. + */ + void setVerbose(unsigned short v); + + /** + * Open a PPS server object. + */ + bool open(const std::string& path, int oflags); + + /** + * Close this PPS server object. + */ + void close(); + + /** + * Send a message to a particular client. + */ + void sendMessage(const std::string& clientID, const std::string& msg); + + /** + * Send a message to all clients. + */ + void broadcastMessage(const std::string& msg); + + /** + * The function that the PPSInterface will call when an event happens. + * This is the static function that is used as a function pointer for + * PPSInterface::setEventFunc(). + * + * @param event The event PPSInterface is sending. + * @param pArg A pointer to a PPSInterfaceGlue object, passed in during + * object construction. + */ + static void onEvent(void* pArg, const PPSEvent& event); + +private: + + /** + * The static PPSInterfaceGlue::onEvent() calls this onEvent to do the actual work. + */ + void onEvent(const PPSEvent& event); + + /** + * Take a ppsObject and turn it into a JSON string to send back to the JavaScript + * with a onMessage event. + */ + std::string JSONEncodeData(const ppsObject& ppsObj) const; + + /** + * Take a JSON string and change it into a PPS consumable string. + */ + std::string JSONDecodeData(const std::string& data) const; + + // String names for the various events + static const std::string EVENT_OPEN; + static const std::string EVENT_CLOSE; + static const std::string EVENT_CLIENT_CONNECT; + static const std::string EVENT_CLIENT_DISCONNECT; + static const std::string EVENT_MESSAGE; + static const std::string EVENT_OPEN_FAILED; + static const std::string EVENT_SEND_MESSAGE_FAILED; + static const std::string EVENT_RECEIVE_MESSAGE_FAILED; + + /** Custom PPS encoding value: an "n" means a real number. */ + static const std::string ENCODING_N; + /** Custom PPS encoding value: a "b" means a boolean value. */ + static const std::string ENCODING_B; + /** Custom PPS encoding value: the data is encoded using JSON. */ + static const std::string ENCODING_JSON; + + // JSON constants + static const Json::StaticString JSON_DATA; + static const Json::StaticString JSON_CONNECTION_ID; + + /** The interface this object wraps. */ + PPSInterface m_interface; + + // Handlers for various events + void* m_pArg; + callback* m_handleOpen; + callback* m_handleClose; + callback* m_handleClientConnect; + callback* m_handleClientDisconnect; + callback* m_handleMessage; + callback* m_handleOpenFailed; + callback* m_handleSendMessageFailed; + callback* m_handleReceiveMessageFailed; + +}; + +} /* namespace jpps */ +#endif /* PPSSERVERGLUE_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PluginTypes.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PluginTypes.h b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PluginTypes.h new file mode 100644 index 0000000..9ce6b32 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/PluginTypes.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#ifndef PLUGINTYPES_H_ +#define PLUGINTYPES_H_ + +namespace jpps { + +/** + * Function type for setting handles between JNext plug-in and glue classes. + */ +typedef void (callback)(void* pArg, const std::string&); + +} + + +#endif /* PLUGINTYPES_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/pluginManifest.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/pluginManifest.cpp b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/pluginManifest.cpp new file mode 100644 index 0000000..e06ad4c --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/plugin/pluginManifest.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#include "JPPSPlugin.h" +#include "JPPSServerPlugin.h" + +#include + +/** + * This callback must be implemented by all JSExt objects. It is invoked from + * plugin.cpp. + * + * @return A comma separated list of classes supported by this JNEXT extension + */ +char* onGetObjList(void) +{ + static char* ppsclasses = NULL; + + if (ppsclasses == NULL) { + + // Get the length of all the strings, +1 for the ',' +1 for the \0 + int size = std::strlen(jpps::JPPSPlugin::CLASS_NAME) + std::strlen(jpps::JPPSServerPlugin::CLASS_NAME) + 1 + 1; + ppsclasses = new char[size]; + std::strcpy(ppsclasses, jpps::JPPSPlugin::CLASS_NAME); + std::strcat(ppsclasses, ","); + std::strcat(ppsclasses, jpps::JPPSServerPlugin::CLASS_NAME); + ppsclasses[size] = '\0'; + } + // Return a comma separated list of classes known to this plugin + return ppsclasses; +} + +/** + * This callback must be implemented by all JSExt objects. It is invoked from + * plugin.cpp. + * + * @param strClassName Name of the class requested to be created Valid named are those + * that are returned in onGetObjList + * + * @param strObjId The unique object id for the class + * + * @return A pointer to the created extension object + */ +JSExt* onCreateObject(const std::string& strClassName, const std::string& strObjId) +{ + // Given a class name and identifier, create the relevant object. + if (strClassName == jpps::JPPSPlugin::CLASS_NAME) { + return new jpps::JPPSPlugin(strObjId);; + } + else if (strClassName == jpps::JPPSServerPlugin::CLASS_NAME) { + return new jpps::JPPSServerPlugin(strObjId); + } + + // Any other name is invalid + return NULL; +} + + http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Logger.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Logger.h b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Logger.h new file mode 100644 index 0000000..37a9d17 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Logger.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#ifndef LOGGER_H_ +#define LOGGER_H_ + +#include + +#include +#include + +namespace jpps { + +/** + * The Logger class writes messages to the system log. It has a verbosity setting + * in order to prevent cluttering the slog during normal operation. + */ +class Logger { + +public: + + enum slogType { + info = _SLOG_INFO, + warning = _SLOG_WARNING, + error = _SLOG_ERROR, + critical = _SLOG_CRITICAL, + debug = _SLOG_DEBUG1 + }; + + /** + * Default constructor. Sets the verbosity to 0; + */ + Logger() : m_verbosity(0) {} + + /** + * Destructor. + */ + ~Logger() {} + + /** + * Set the desired level of verbosity. A value of 0 means that only warning, + * error and critical messages will appear in the slog. A verbosity of 1 adds + * info messages. A verbosity of 2 adds debug messages. + */ + inline void setVerbosity(unsigned short value) { m_verbosity = value; } + + /** + * Get the current level of verbosity. + */ + inline unsigned short getVerbosity() const { return m_verbosity; } + + /** + * Used to send messages to the system log (slog). + * + * @param type The type of slog message. + * @param message The message to put in the slog. + */ + void slog(const slogType& type, const std::string& message) const { + + // Don't display info or debug when verbosity is set to 0 + if (m_verbosity == 0 && (type == info || type == debug)) return; + // Don't display debug when verbosity is set to 1 + if (m_verbosity == 1 && type == debug) return; + + ::slogf(_SLOG_SETCODE(_SLOGC_GRAPHICS, 300), type, "%s", message.c_str()); + } + +private: + + /** The verbosity level. */ + unsigned short m_verbosity; +}; + +} + +#endif /* LOGGER_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.cpp b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.cpp new file mode 100644 index 0000000..82ab5d1 --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +#include "Thread.h" +#include +#include "Logger.h" +#include +#include +#include + +namespace jpps { + +Thread::Thread() +: m_threadID(-1) +{ + // Init the thread with all defaults + pthread_attr_init(&m_attrib); +} + +Thread::~Thread() +{ + // Dispose of the thread attributes + pthread_attr_destroy(&m_attrib); +} + +void Thread::start(void* (*start_routine)(void*), void* arg, const std::string& thread_name) +{ + // If this thread is already started, you can't start a new one + if (m_threadID != -1) { + return; + } + + // Create a new thread + if (pthread_create(&m_threadID, &m_attrib, start_routine, arg) != 0) { + + std::ostringstream ostream; + ostream << "Thread::start() Failed - Failed to create a new thread. " + << " (" << errno << ": " << strerror(errno) << ")"; + + Logger logger; + logger.slog(Logger::warning, ostream.str()); + } + + if (!thread_name.empty()) + pthread_setname_np(m_threadID, thread_name.c_str()); +} + +void Thread::stop() +{ + // If the thread wasn't running, we can't stop it + if (m_threadID == -1) { + return; + } + + // Cancel the thread + if (pthread_cancel(m_threadID) != 0) { + + std::ostringstream ostream; + ostream << "Thread::stop() Failed - Failed to cancel thread " << m_threadID << "." + << " (" << errno << ": " << strerror(errno) << ")"; + + Logger logger; + logger.slog(Logger::warning, ostream.str()); + } + + // Reset the thread ID + m_threadID = -1; +} + +} /* namespace jpps */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.h b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.h new file mode 100644 index 0000000..79cc62a --- /dev/null +++ b/blackberry10/bin/templates/project/plugins/JPPS/native/src/utils/Thread.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2012 Research In Motion Limited. All rights reserved. + */ + +/* + * $QNXLicenseC: + * Copyright 2009, QNX Software Systems. All Rights Reserved. + * + * You must obtain a written license from and pay applicable license fees to QNX + * Software Systems before you may reproduce, modify or distribute this software, + * or any work that includes all or part of this software. Free development + * licenses are available for evaluation and non-commercial purposes. For more + * information visit http://licensing.qnx.com or email licensing@qnx.com. + * + * This file may contain contributions from others. Please review this entire + * file for other proprietary rights or license notices, as well as the QNX + * Development Suite License Guide at http://licensing.qnx.com/license-guide/ + * for other information. + * $ + */ + +#ifndef THREAD_H_ +#define THREAD_H_ + +#include +#include + +namespace jpps { + +/** + * Simple wrapper to simplify thread management. + */ +class Thread { + +public: + + /** + * Constructor. + */ + Thread(); + + /** + * Destructor. + */ + virtual ~Thread(); + + /** + * Start a thread with the given function. If the thread is already running and has not + * been stopped, this does nothing. + */ + void start(void* (*start_routine)(void*), void* arg, const std::string& thread_name = ""); + + /** + * Stop the thread. If the thread isn't running, this does nothing. + */ + void stop(); + + /** + * Is the thread running? + */ + inline bool isRunning() const { return (m_threadID >= 0); } + +private: + + /** The id of this thread. */ + pthread_t m_threadID; + + /** The attributes of this thread. */ + pthread_attr_t m_attrib; +}; + +} /* namespace jpps */ +#endif /* THREAD_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/Makefile ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/Makefile b/blackberry10/bin/templates/project/plugins/JPPS/src/Makefile deleted file mode 100644 index 0e22650..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -LIST=VARIANT -ifndef QRECURSE -QRECURSE=recurse.mk -ifdef QCONFIG -QRDIR=$(dir $(QCONFIG)) -endif -endif -include $(QRDIR)$(QRECURSE) http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/Makefile ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/Makefile b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/Makefile deleted file mode 100644 index 0e22650..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -LIST=VARIANT -ifndef QRECURSE -QRECURSE=recurse.mk -ifdef QCONFIG -QRDIR=$(dir $(QCONFIG)) -endif -endif -include $(QRDIR)$(QRECURSE) http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/Makefile ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/Makefile b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/Makefile deleted file mode 100644 index 0cc5eae..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -LIST=CPU -ifndef QRECURSE -QRECURSE=recurse.mk -ifdef QCONFIG -QRDIR=$(dir $(QCONFIG)) -endif -endif -include $(QRDIR)$(QRECURSE) http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/common.mk ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/common.mk b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/common.mk deleted file mode 100644 index 6cecca9..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/common.mk +++ /dev/null @@ -1,34 +0,0 @@ -ifndef QCONFIG -QCONFIG=qconfig.mk -endif -include $(QCONFIG) - -NAME=jpps -PLUGIN=yes -UTILS=yes - -include ../../../../../../meta.mk - -override CCFLAGS := $(filter-out -Werror , $(CCFLAGS)) - -EXTRA_SRCVPATH+=$(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/utils \ - $(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/core \ - $(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/plugin - -EXTRA_INCVPATH+=$(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/utils \ - $(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/core \ - $(WEBWORKS_DIR)/plugin/com.blackberry.jpps/src/blackberry10/native/src/plugin - -SRCS+=src/utils/Thread.cpp \ - src/core/PPSInterface.cpp \ - src/core/PPSNotifier.cpp \ - src/core/PPSNotifyGroupManager.cpp \ - src/plugin/JPPSPlugin.cpp \ - src/plugin/PPSInterfaceGlue.cpp \ - src/plugin/JPPSServerPlugin.cpp \ - src/plugin/PPSServerGlue.cpp \ - src/plugin/pluginManifest.cpp - -include $(MKFILES_ROOT)/qtargets.mk - -LIBS+=pps http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/device/libjpps.so ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/device/libjpps.so b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/device/libjpps.so deleted file mode 100644 index f0eb90d..0000000 Binary files a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/device/libjpps.so and /dev/null differ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/simulator/libjpps.so ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/simulator/libjpps.so b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/simulator/libjpps.so deleted file mode 100644 index f2c12ff..0000000 Binary files a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/simulator/libjpps.so and /dev/null differ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSEvent.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSEvent.h b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSEvent.h deleted file mode 100644 index 808e699..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSEvent.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - */ - -/* - * $QNXLicenseC: - * Copyright 2009, QNX Software Systems. All Rights Reserved. - * - * You must obtain a written license from and pay applicable license fees to QNX - * Software Systems before you may reproduce, modify or distribute this software, - * or any work that includes all or part of this software. Free development - * licenses are available for evaluation and non-commercial purposes. For more - * information visit http://licensing.qnx.com or email licensing@qnx.com. - * - * This file may contain contributions from others. Please review this entire - * file for other proprietary rights or license notices, as well as the QNX - * Development Suite License Guide at http://licensing.qnx.com/license-guide/ - * for other information. - * $ - */ - -#ifndef PPSEVENT_H_ -#define PPSEVENT_H_ - -#include -#include "PPSTypes.h" - -namespace jpps { - -/** - * A class representing a PPS event. Used to notify interested parties when something - * happens to a PPS object. - */ -class PPSEvent { - -public: - - /** - * The possible types of this event. - */ - enum PPSEventType { - /** The PPS object's first data read is complete. */ - PPS_EVENT_FIRST_READ_COMPLETE, - /** The PPS object has new data. */ - PPS_EVENT_NEW_DATA, - /** The PPS object was successfully opened. */ - PPS_EVENT_OPENED, - /** A PPS object was closed. */ - PPS_EVENT_CLOSED, - /** An attempt to open a PPS object failed. */ - PPS_EVENT_OPEN_FAILED, - /** An attempt to read from a PPS object failed. */ - PPS_EVENT_READ_FAILED, - /** An attempt to write to a PPS object failed. */ - PPS_EVENT_WRITE_FAILED, - }; - - /** - * Constructor. - * - * @param eventType The type of event this is. - * @param data If eventType == PPS_EVENT_NEW_DATA, the new data. - */ - PPSEvent(PPSEventType eventType, const std::string& msg = "", const ppsObject& newData = ppsObject()) - : m_eventType(eventType) - , m_message(msg) - , m_newData(newData) - {} - - /** - * Destructor. - */ - virtual ~PPSEvent() {} - - /** - * Get the event type. - */ - inline PPSEventType getEventType() const { return m_eventType; } - - /** - * Get the message associated with this event. - */ - inline std::string getMessage() const { return m_message; } - - /** - * Get the new data. This value is only populated if the eventType is PPS_EVENT_NEW_DATA. This data - * is what was parsed out of the PPS object. - */ - inline ppsObject getNewData() const { return m_newData; } - -private: - - // Disable the default constructor. - PPSEvent(); - - /** The type of this event. */ - PPSEventType m_eventType; - - /** A message associated to the event. */ - std::string m_message; - - /** If m_eventType == PPS_EVENT_NEW_DATA, this contains the new data. Else m_newData is empty. - * This data is the data that was read from the PPS object, un-massaged. */ - ppsObject m_newData; -}; - -} /* namespace jpps */ -#endif /* PPSEVENT_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.cpp b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.cpp deleted file mode 100644 index dfb575b..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.cpp +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - */ - -#include "PPSInterface.h" - -#include - -#include -#include -#include -#include - -#include "PPSNotifyGroupManager.h" -#include "PPSEvent.h" - -namespace jpps { - -// Const statics -const char* PPSInterface::PPS_ROOT = "/pps/"; -const int PPSInterface::MaxPPSReadSize = (32 * 1024); - -// Static data members -pthread_mutex_t PPSInterface::sm_mutex = PTHREAD_MUTEX_INITIALIZER; -pthread_mutex_t PPSInterface::sm_cond; -volatile bool PPSInterface::sm_firstInitDone = false; -std::map PPSInterface::sm_interfaceLookupTable; - -PPSInterface::PPSInterface() -: m_pEventFunc(NULL) -, m_pEventArg(NULL) -, m_interfaceId(0) -, m_fd(-1) -, m_oflags(0) -, m_firstRead(true) -, m_cachedRead() -, m_logger() -{ - // This is used to assign a unique ID to each PPSInterface object - static unsigned int interfaceIDs = 0; - - ::pthread_mutex_lock(&sm_mutex); - - m_interfaceId = interfaceIDs; - interfaceIDs++; // Increment this so that the next object has a unique id. - - // Add myself to the lookup table - sm_interfaceLookupTable.insert(std::pair(m_interfaceId, this)); - - if (!sm_firstInitDone) { - - // Initialize the condvar - pthread_condattr_t condAttr; - ::pthread_condattr_init(&condAttr); - ::pthread_condattr_setclock(&condAttr, CLOCK_MONOTONIC); - ::pthread_cond_init(&sm_cond, &condAttr); - ::pthread_condattr_destroy(&condAttr); - - sm_firstInitDone = true; - } - - ::pthread_mutex_unlock(&sm_mutex); -} - -PPSInterface::~PPSInterface() -{ - std::ostringstream ostream; - ostream << "PPSInterface::~PPSInterface() - Destruct fd:" << m_fd << "."; - m_logger.slog(Logger::debug, ostream.str()); - - // Close my open PPS object, if I have one - close(); - - // Remove myself from the lookup table - sm_interfaceLookupTable.erase(m_interfaceId); -} - -void PPSInterface::setVerbose(unsigned short v) -{ - m_logger.setVerbosity(v); -} - -void PPSInterface::setEventFunc(const PPSEventFunc* pEventFunc, void* pArg) -{ - m_pEventFunc = pEventFunc; - m_pEventArg = pArg; -} - -bool PPSInterface::open(const std::string& path, int oflag, int mode, bool server) -{ - // If we've already got an open file, fail - if (m_fd != -1) { - - m_logger.slog(Logger::warning, "PPSInterface::open() Failed - Attempted to open an object that is already open."); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_OPEN_FAILED, "Attempted to open an object that is already open.")); - return false; - } - - std::string errorMsg; - bool ok = false; - - // Prepend PPS_ROOT to the path if it doesn't start with a '/' - std::string fullpath = (path[0] != '/' ? PPSInterface::PPS_ROOT : "") + path; - - // This flag is used to prevent the notify thread from performing reads while the - // open() function is running and doing its first read. - ::pthread_mutex_lock(&sm_mutex); - m_firstRead = true; - ::pthread_mutex_unlock(&sm_mutex); - - // Remove any options from the path otherwise lstat will fail - std::string pathNoOptions(fullpath); - std::size_t nPosOpts = fullpath.rfind('?'); - - if (nPosOpts != std::string::npos) - pathNoOptions = fullpath.substr(0, nPosOpts); - - // There are a few complexities associated with symbolic links. If - // the last component of the path is a symlink we have to resolve it - // since we won't be able to resolve the name when the options are - // added. Also we need to get the path relative to the pps filesystem - // so we can locate the .notify file. So, if the object already - // exists, resolve the path. If it doesn't and O_CREAT is specified - // resolve the directory it's in, otherwise it's a failure. - std::string resolvedName; - char szResolvedName[PATH_MAX+128]; // buffer for use with the C functions - - if (::realpath(pathNoOptions.c_str(), szResolvedName) != NULL) { - - resolvedName = szResolvedName; - ok = true; - } - else if (oflag & O_CREAT) { - - // Chop off the file name, so we can try to resolve the directory - size_t nPos = pathNoOptions.rfind('/'); - - // We found a '/' - if (nPos != std::string::npos) { - - // Get the directory path - std::string dirPath = pathNoOptions.substr(0, nPos); // Don't include the '/' - - if (::realpath(dirPath.c_str(), szResolvedName) != NULL) { - - // Concatenate the file name to the resolved directory path - resolvedName = szResolvedName + pathNoOptions.substr(nPos); // include the '/' at the start - ok = true; - } - } - } - - if (ok) { - - struct stat info; - int result = ::lstat(resolvedName.c_str(), &info); - - if (result != 0) { - - // If we failed and we're not creating a non-existent file, it's an error. - if ((errno != ENOENT) && !(oflag & O_CREAT)) - ok = false; - } - else if (S_ISDIR(info.st_mode)) - ok = false; - } - - if (ok) { - - std::string options; - - // Now lets work with the options to ensure we have a complete version - std::string pathOptions; - - // Get just the stuff after '?' - size_t nPos = fullpath.rfind('?'); - - if (nPos != std::string::npos) { - pathOptions = fullpath.substr(nPos); - } - - if ((oflag & O_ACCMODE) != O_WRONLY) { - - // This is used as the return object for the joinNotifyGroup() call - // It's only valid if joinNotifyGroup() returned true - std::string groupId; - - PPSNotifyGroupManager::mutexLock(); - PPSNotifyGroupManager& notifyManager = PPSNotifyGroupManager::getInstance(); - bool groupJoined = notifyManager.joinNotifyGroup(resolvedName, groupId); - PPSNotifyGroupManager::mutexUnlock(); - - if (groupJoined) { - - // If we're acting as a server, we use server as an option - // otherwise we have to specify delta mode. PPS has a fit - // if we specify both delta and deltadir so check for this. - std::string modeExtra; - - // Add in the options we need. If both server and delta are specified, use only - // server (it kind of implies delta and at one point pps would not like both being - // present) - if (server) { - modeExtra = ",server"; - } - // If we have no options or there's no 'deltadir' specified, use delta mode - else if (pathOptions.empty() || pathOptions.find("deltadir") == std::string::npos) { - modeExtra = ",delta"; - } - - // We embed the m_interfaceID as a unique identifier that will be passed on to the - // PPSNotifier. PPSNotifier will use this id in conjunction with getPPSInterface() - // in order to send this object notifications that content is ready for reading later. - std::ostringstream ostream; - ostream << "?" << (pathOptions.empty() ? "" : pathOptions.substr(1) + ",") << "notify=" - << groupId << ":" << m_interfaceId << modeExtra; - options = ostream.str(); - } - } - - if (!options.empty()) { - - resolvedName += options; - } - - // The big moment... Let's try to actually open the PPS object... - if (ok) { - m_fd = ::open(resolvedName.c_str(), oflag, mode); - } - - // Error opening the PPS object - if (m_fd < 0) { - - std::ostringstream ostream; - ostream << "PPSInterface::open() Failed - ::open(" - << (((oflag & O_ACCMODE) == O_WRONLY) ? "write" : - ((oflag & O_ACCMODE) == O_RDONLY) ? "read" : - ((oflag & O_ACCMODE) == O_RDWR) ? "r/w" : "???") - << ((oflag & O_CREAT) ? ":create" : "") - << ") " << resolvedName << " (" << errno << ": " << strerror(errno) << ")"; - m_logger.slog(Logger::warning, ostream.str()); - errorMsg = ostream.str(); - } - else { - // Depending on our umask, the permissions might not have - // been as specified. So if O_CREAT was specified, re-set the - // permissions. The object might already exist, but perhaps - // that's OK too. - if (oflag & O_CREAT) { - ::fchmod(m_fd, mode); - } - - m_oflags = oflag; - - std::ostringstream ostream; - ostream << "PPSInterface::open() - ::open(" - << (((oflag & O_ACCMODE) == O_WRONLY) ? "write" : - ((oflag & O_ACCMODE) == O_RDONLY) ? "read" : - ((oflag & O_ACCMODE) == O_RDWR) ? "r/w" : "???") - << ((oflag & O_CREAT) ? ":create" : "") - << ") " << resolvedName; - m_logger.slog(Logger::debug, ostream.str()); - } - } - // For whatever reason, the path to the PPS object was not valid - else { - std::ostringstream ostream; - ostream << "PPSInterface::open() Failed - ::open(" - << (((oflag & O_ACCMODE) == O_WRONLY) ? "write" : - ((oflag & O_ACCMODE) == O_RDONLY) ? "read" : - ((oflag & O_ACCMODE) == O_RDWR) ? "r/w" : "???") - << ((oflag & O_CREAT) ? ":create" : "") - << ") " << path << " The PPS object could not be resolved properly."; - m_logger.slog(Logger::warning, ostream.str()); - errorMsg = ostream.str(); - } - - sendEvent(PPSEvent(m_fd >= 0 ? PPSEvent::PPS_EVENT_OPENED : PPSEvent::PPS_EVENT_OPEN_FAILED, errorMsg)); - - if (m_fd >= 0 && (oflag & O_ACCMODE) != O_WRONLY) { - - // Perform the initial read - readFromObject(); - } - - // Tell the other thread we are done with the first read - ::pthread_mutex_lock(&sm_mutex); - m_firstRead = false; - ::pthread_cond_broadcast(&sm_cond); - ::pthread_mutex_unlock(&sm_mutex); - - return m_fd >= 0; -} - -void PPSInterface::write(const std::string& data) -{ - // We're trying to write to an unopened PPS object - if (m_fd == -1) { - - std::string msg("PPSInterface::write() Failed - Attempting to write to a file that isn't open."); - m_logger.slog(Logger::warning, msg); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_WRITE_FAILED, msg)); - } - - ssize_t ret = ::write(m_fd, data.c_str(), data.length()); - - // Debug slog the write call if it was successful - if (ret >= 0) { - - std::ostringstream ostream; - ostream << "PPSInterface::write() - fd:" << m_fd << " : \n" << data; - m_logger.slog(Logger::debug, ostream.str()); - } - - // There was an error writing - if (ret == -1) { - - std::ostringstream ostream; - ostream << "PPSInterface::write() Failed - Error writing to fd:" << m_fd << " (" << errno << ": " << strerror(errno) << ")"; - m_logger.slog(Logger::warning, ostream.str()); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_WRITE_FAILED, ostream.str())); - } - - // If we wrote successfully and the file is open in read/write mode, then we need to manually update the - // read cache. When in O_RDWR mode, we do NOT receive notifications of our own write() operations. - // This means that the cache of read data becomes stale - it is missing the data that we have written - // to the object ourselves. In this case, we will manually update the cache. - // NOTE: this seems fraught with peril, but unfortunately there don't seem to be any good solutions to - // fixing the problem of read/write mode and read() integrity. - if (ret >= 0 && (m_oflags & O_RDWR)) { - - // We're going to try to fool the ppsparse() method into parsing the data we write. - char* pWriteData = new char[data.length() + 1]; - - // The later call to ppsparse() moves the pWriteData pointer forward, and we need the original pointer - // in order to properly delete the object later, so let's cache it here - char* pWriteDataCopy = pWriteData; - - std::strcpy(pWriteData, data.c_str()); // strcpy null terminates for us - - // Parse the write buffer - this should give us a ppsObject with only attributes - ppsObject parsedData = parsePPSData(pWriteData); - - // The data being written does not include the object name other object properties (duh) - // So parsedData contains only attribute info. We want to preserve the object name - // and properties, so lets just copy the ones in the cache into our parsedData struct - // so that the call to updateCachedReadData() will preserve them (i.e. copy them back) - parsedData.name = m_cachedRead.name; - parsedData.flags = m_cachedRead.flags; - parsedData.options = m_cachedRead.options; - parsedData.optionMask = m_cachedRead.optionMask; - - // Update the cache - updateCachedReadData(parsedData); - - // Cleanup our allocated memory - if (pWriteDataCopy) { - - delete[] pWriteDataCopy; - } - } -} - -void PPSInterface::sync() -{ - if (m_fd >= 0) - ::fsync(m_fd); -} - -void PPSInterface::close() -{ - if (m_fd >= 0) { - - ::close(m_fd); - m_fd = -1; - m_cachedRead = ppsObject(); - m_oflags = 0; - - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_CLOSED)); - } -} - -void PPSInterface::onNotify(NotifyType event) -{ - // We only handle read notifications - if (event != PPS_READ) { - return; - } - - if (m_firstRead) { - ::pthread_mutex_lock(&sm_mutex); - while (m_firstRead) { - ::pthread_cond_wait(&sm_cond, &sm_mutex); - } - ::pthread_mutex_unlock(&sm_mutex); - } - - readFromObject(); -} - -void PPSInterface::readFromObject() -{ - bool sendFirstReadEvent = m_firstRead; - - // This was a uint8_t - was there a reason? - char szBuffer[MaxPPSReadSize + 1]; - int bufferLen; - - // Read from the actual PPS file - this call is not blocking - while ((bufferLen = ::read(m_fd, szBuffer, MaxPPSReadSize)) > 0) { - - if (bufferLen <= MaxPPSReadSize) { - - // Make sure the buffer is null terminated. - szBuffer[bufferLen] = '\0'; - - std::string buf(szBuffer, bufferLen); - std::ostringstream ostream; - ostream << "PPSInterface::readFromObject() - fd:" << m_fd << " len:" << bufferLen << "\n" << buf; - m_logger.slog(Logger::debug, ostream.str()); - - // Parse the PPS data - ppsObject parsedPPS = parsePPSData(szBuffer); - - // Update the cache with the data we just read - updateCachedReadData(parsedPPS); - - // If this is the first read, then send the first read event. - if (sendFirstReadEvent) { - - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_FIRST_READ_COMPLETE, "", parsedPPS)); - sendFirstReadEvent = false; - } - else { - - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_NEW_DATA, "", parsedPPS)); - } - } - else { - - std::ostringstream ostream; - ostream << "PPSInterface::readFromObject() Failed - fd:" << m_fd << " oversized message len:" << bufferLen << "."; - m_logger.slog(Logger::warning, ostream.str()); - } - } - - if (bufferLen == -1) { - - std::ostringstream ostream; - ostream << "PPSInterface::readFromObject() Failed - Error reading from fd:" << m_fd << " (" << errno << ": " << strerror(errno) << ")"; - m_logger.slog(Logger::warning, ostream.str()); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_READ_FAILED, ostream.str())); - } - - // It's possible that we won't go into the while() loop above (sometimes the first read is legitimately empty) - // in which case, we still need to send a first read complete event - if (sendFirstReadEvent) { - - // Send an empty first read object - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_FIRST_READ_COMPLETE, "", ppsObject())); - sendFirstReadEvent = false; - } -} - -void PPSInterface::sendEvent(const PPSEvent& event) const -{ - if (m_pEventFunc) { - m_pEventFunc(m_pEventArg, event); - } -} - -PPSInterface* const PPSInterface::getPPSInterface(const unsigned int id) -{ - ::pthread_mutex_lock(&sm_mutex); - - std::map::iterator it = sm_interfaceLookupTable.find(id); - - if (it != sm_interfaceLookupTable.end()) { - - ::pthread_mutex_unlock(&sm_mutex); - return (*it).second; - } - - ::pthread_mutex_unlock(&sm_mutex); - return NULL; -} - -ppsObject PPSInterface::parsePPSData(char* data) const -{ - // This is the structure that will contain parsed data for each line of the PPS object - // It needs to be initialized to NULL - pps_attrib_t info; - std::memset(&info, 0, sizeof(info)); - - // The return code for each PPS line that gets parsed - pps_status_t rc; - ppsObject ppsObj; - - while ((rc = ::ppsparse(&data, NULL, NULL, &info, 0)) != PPS_END) { - - if (rc == -1) { - - std::ostringstream ostream; - ostream << "PPSInterface::parsePPSData() Failed - Error calling ppsparse() fd:" << m_fd << " (" << errno << ": " << strerror(errno) << ")"; - m_logger.slog(Logger::warning, ostream.str()); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_READ_FAILED, ostream.str())); - } - - if (info.flags & PPS_INCOMPLETE) { - m_logger.slog(Logger::debug, "PPSInterface::parsePPSData - PPS data incomplete."); - } - - switch (rc) { - - // When the object has been modified, update the object settings - case PPS_OBJECT: - case PPS_OBJECT_CREATED: - case PPS_OBJECT_DELETED: - case PPS_OBJECT_TRUNCATED: - { - ppsObj.name = info.obj_name; - ppsObj.flags = info.flags; - ppsObj.options = info.options; - ppsObj.optionMask = info.option_mask; - break; - } - - // An attribute has been updated - case PPS_ATTRIBUTE: - case PPS_ATTRIBUTE_DELETED: - { - ppsAttribute ppsAttrib; - ppsAttrib.name = info.attr_name; - - // Value and encoding aren't valid if rc == PPS_ATTRIBUTE_DELETED - if (rc == PPS_ATTRIBUTE) { - - ppsAttrib.value = info.value; - ppsAttrib.encoding = info.encoding; - } - - ppsAttrib.flags = info.flags; - ppsAttrib.options = info.options; - ppsAttrib.optionMask = info.option_mask; - - ppsObj.attributes.insert(ppsAttrPair(ppsAttrib.name, ppsAttrib)); - break; - } - - case PPS_ERROR: - { - std::string msg("PPSInterface::parsePPSData() Failed - Error parsing PPS data."); - m_logger.slog(Logger::warning, msg); - sendEvent(PPSEvent(PPSEvent::PPS_EVENT_READ_FAILED, msg)); - break; - } - - case PPS_END: - default: - break; - } - - } - - return ppsObj; -} - -void PPSInterface::updateCachedReadData(const ppsObject& newData) -{ - ::pthread_mutex_lock(&sm_mutex); - - // Update the object - m_cachedRead.name = newData.name; - m_cachedRead.flags = newData.flags; - m_cachedRead.options = newData.options; - m_cachedRead.optionMask = newData.optionMask; - - ::pthread_mutex_unlock(&sm_mutex); - - // Update the attributes - for (const_ppsAttrIter it = newData.attributes.begin(); it != newData.attributes.end(); it++) { - - ppsAttribute attr = (*it).second; - - // An attribute is being deleted - if (attr.flags & PPS_DELETED) { - - ::pthread_mutex_lock(&sm_mutex); - - // Look for this attribute in the cache and remove it - ppsAttrIter findIt = m_cachedRead.attributes.find(attr.name); - - if (findIt != m_cachedRead.attributes.end()) { - m_cachedRead.attributes.erase(findIt); - } - - ::pthread_mutex_unlock(&sm_mutex); - } - // We're adding a new attribute - don't search for it - else if (attr.flags & PPS_CREATED){ - - ::pthread_mutex_lock(&sm_mutex); - m_cachedRead.attributes.insert(ppsAttrPair(attr.name, attr)); - ::pthread_mutex_unlock(&sm_mutex); - } - else { - - ::pthread_mutex_lock(&sm_mutex); - - // Look for this attribute in the cache - ppsAttrIter findIt = m_cachedRead.attributes.find(attr.name); - - // If we find it, update the attribute values - if (findIt != m_cachedRead.attributes.end()) { - - (*findIt).second.name = attr.name; - (*findIt).second.encoding = attr.encoding; - (*findIt).second.value = attr.value; - (*findIt).second.flags = attr.flags; - (*findIt).second.options = attr.options; - (*findIt).second.optionMask = attr.optionMask; - } - // If we don't find it, insert it - else { - m_cachedRead.attributes.insert(ppsAttrPair(attr.name, attr)); - } - ::pthread_mutex_unlock(&sm_mutex); - } - } -} - -} /* namespace jpps */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.h b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.h deleted file mode 100644 index 0fde80c..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSInterface.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - */ - -/* - * $QNXLicenseC: - * Copyright 2009, QNX Software Systems. All Rights Reserved. - * - * You must obtain a written license from and pay applicable license fees to QNX - * Software Systems before you may reproduce, modify or distribute this software, - * or any work that includes all or part of this software. Free development - * licenses are available for evaluation and non-commercial purposes. For more - * information visit http://licensing.qnx.com or email licensing@qnx.com. - * - * This file may contain contributions from others. Please review this entire - * file for other proprietary rights or license notices, as well as the QNX - * Development Suite License Guide at http://licensing.qnx.com/license-guide/ - * for other information. - * $ - */ - -#ifndef PPS_H_ -#define PPS_H_ - -#include -#include - -#include - -#include "PPSTypes.h" -#include "PPSEvent.h" -#include "../utils/Logger.h" - -namespace jpps { - -/** - * This class augments standard PPS functionality by providing events for when PPS objects are opened, - * closed, have new data, etc. - * - * When a PPS object is opened using PPSInterface::open(), the object is opened as part of a notification group - * managed by PPSNotifyGroupManager. The notification group monitors the PPS object and notifies PPSInterface - * whenever there is new data available in the PPS object. - * - * PPSInterface should be used in order to simplify PPS object monitoring (i.e. watching for new data in a PPS - * object.) PPSInterface takes over management of watching for new data and uses a notification callback mechanism - * with a defined set of possible events to inform the client of changes to the PPS object. - */ -class PPSInterface { - -public: - - /** - * Used with onNotify to allow the PPSNotifier to tell us what type of notification - * message it is sending. - */ - enum NotifyType { - /** The .notify object received a notification that data is ready to be read. */ - PPS_READ = 0, - /** The .notify object received a notification that a file being watched is closing. */ - PPS_CLOSE = 1 }; - - /** - * Constructor. - */ - PPSInterface(); - - /** - * Destructor. - */ - ~PPSInterface(); - - /** - * Set up a function to call to be notified about PPS events. - * - * @param pEventFunc The function to call whenever an event happens in PPSInterface. - * @param pArg An optional parameter that will be passed back to pEventFunc every time it - * is called. PPSInterface will not modify pArg. - */ - void setEventFunc(const PPSEventFunc* pEventFunc, void* pArg = NULL); - - /** - * Enable verbose mode. Increase the number of �v�s to increase verbosity. - * - * @param v The level of verbosity. A value of 0 is off, 1 shows info messages, 2 shows - * debug messages. - */ - void setVerbose(unsigned short v); - - /** - * Open a PPS object. If the open() call is successful, a PPS_EVENT_OPENED event will be sent. - * The PPS object will be read as part of the open operation and the PPS_EVENT_FIRST_READ_COMPLETE - * will be sent when the first read is complete. Note that there may be a PPS_EVENT_NEW_DATA - * event *before* the PPS_EVENT_FIRST_READ_COMPLETE event, or there may not be. - * PPS_EVENT_FIRST_READ_COMPLETE only guarantees that at least one read has been performed, not - * that it will be the first read event to fire. - * - * If the open operation fails, the function returns false and a PPS_EVENT_OPEN_FAILED will be sent. - * - * @param path The PPS file/directory path. - * @param oflags Flags passed to ::open. - * @param mode Mode passed to ::open. - * @param serverMode If true, open the object in server mode as the server. - * @return True if the open was successful, false otherwise. - */ - bool open(const std::string& path, int oflags, int mode, bool serverMode); - - /** - * Check if this PPS object is open. - * @return True if the file is open, false otherwise. - */ - inline bool isOpen() const { return m_fd >= 0; } - - /** - * Write data to a PPS object. - * @param data The data to write to the PPS object. - */ - void write(const std::string& data); - - /** - * Read PPS data. Note that this reads cached data from the last read performed when a - * new data available notification was received. - * - * @return A structured representation of the PPS object, culled from a call to ppsparse() - * a function found in ppsparse.h. - */ - - inline ppsObject read() const { return m_cachedRead; } - - /** - * Close this PPS object. - */ - void close(); - - /** - * Forces all queued I/O operations for this object to finish, synchronizing the file's state. - * The function blocks until this is finished. - */ - void sync(); - - /** - * Called to notify us that there is data ready to be read. - * - * @param event The type of event we're being notified about. - */ - void onNotify(NotifyType event); - - /** - * Given a unique id, return the PPSInterface* matching that id. - * - * Every PPSInterface object is assigned a unique identifier at construction. This - * unique identifier can be used to get a pointer to a PPSInterface at runtime. - * - * In particular, the PPSNotifier gets notifications with this number embedded in them. - * Using this id, the PPSNotifier can callback into the correct PPSInterface instance. - * - * @param id An id that uniquely identifies a PPSInterface object. - * @return a PPSInterface* or NULL if no object matches the given id. - */ - static PPSInterface* const getPPSInterface(const unsigned int id); - -private: - - /** - * Read from the PPS object. Generally this function is called by onNotify() when - * the notifier thread is notified that there is data to be read. This function - * performs a read() of the PPS object that is non-blocking. - */ - void readFromObject(); - - /** - * Given data from a PPS read, parse the PPS data. - */ - ppsObject parsePPSData(char* data) const; - - /** - * Given new PPS data, update the cached read value. - */ - void updateCachedReadData(const ppsObject& newData); - - /** - * Call the function set in setEventFunc() with the given event. - * - * @param event The event to send. - */ - void sendEvent(const PPSEvent& event) const; - - /** The default PPS location. */ - static const char* PPS_ROOT; - - /** The maximum amount of data that can be read from a PPS object. */ - static const int MaxPPSReadSize; - - /** The function to call to notify about PPS events. */ - PPSEventFunc* m_pEventFunc; - - /** An argument that goes with m_pEventFunc. PPSInterface does not modify or use - * this parameter - we simply send it back with every m_pEventFunc call. */ - void* m_pEventArg; - - /** An identifier that uniquely identifies this PPSInterface object. This is used to look up - * this object in a global table. */ - unsigned int m_interfaceId; - - /** The file descriptor of the PPS object being opened. */ - int m_fd; - - /** The open mode flags used when this object was opened. */ - int m_oflags; - - /** If true, main thread is performing initial open/read of PPS object. This is shared - * across threads and needs to be mutexed when accessed.*/ - volatile bool m_firstRead; - - /** The data from the last read performed. */ - ppsObject m_cachedRead; - - /** The logger used to log error messages */ - Logger m_logger; - - /** Mutex used to prevent threads from clobbering each other. */ - static pthread_mutex_t sm_mutex; - - /** Condvar used for multi-thread signaling. */ - static pthread_cond_t sm_cond; - - /** Used to ensure that initialization of statics happens only once. This is shared - * across threads and needs to be mutexed when accessed.*/ - static volatile bool sm_firstInitDone; - - /** The PPSNotifier needs a way to transform an id that uniquely identifies a PPSInterface object - * into an actual PPSInterface*. When we construct a new PPSInterface, we will assign it a unique id - * and we will put the id and the pointer to the object into this table. The table can then be used - * to lookup this object from its unique id. */ - static std::map sm_interfaceLookupTable; -}; - -} /* namespace jpps */ -#endif /* PPS_H_ */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.cpp ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.cpp b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.cpp deleted file mode 100644 index 7869a56..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - */ - -#include "PPSNotifier.h" - -#include - -#include - -#include "PPSInterface.h" -#include "../utils/Logger.h" - -namespace jpps { - -PPSNotifier::PPSNotifier() -: m_notifyObjPath("") -, m_notifyObjFd(-1) -, m_notifyGroupId("") -, m_thread() -{ - -} - -PPSNotifier::~PPSNotifier() -{ - // Stop the thread - m_thread.stop(); - - // Close the .notify file - if (m_notifyObjFd >= 0) { - ::close(m_notifyObjFd); - } -} - -void PPSNotifier::startNotifyLoop() -{ - m_thread.start(_notifyLoop, this, "plugin_jPPS_PPSNotifier(" + m_notifyObjPath + "/.notify)"); -} - - -void* PPSNotifier::_notifyLoop(void* pArg) -{ - // Something is messed up - if (pArg == NULL) - return NULL; - - PPSNotifier* pNotifier = static_cast (pArg); - - // pArg is supposed to be a PPSNotifier object... - if (pNotifier == NULL) - return NULL; - - pNotifier->notifyLoop(); - - return NULL; -} - -void PPSNotifier::notifyLoop() -{ - // Buffer for read() operation - char szData[256]; - int dataLen; - - // This is a blocking read call: this will wait in this loop forever - while ((dataLen = ::read(m_notifyObjFd, szData, sizeof(szData)-1)) > 0) { - - szData[dataLen] = '\0'; - std::string data(szData); - - if ((unsigned int)dataLen > sizeof(szData)-1) { - - std::ostringstream ostream; - ostream << "PPSNotifier::notifyLoop() - Notify read overflow " << dataLen << "."; - Logger logger; - logger.slog(Logger::error, ostream.str()); - } - - std::size_t nPos = data.find('\n'); - - // While we find linefeeds - while(nPos != std::string::npos) { - - // Read the first char - PPSInterface::NotifyType event = data[0] == '-' ? PPSInterface::PPS_CLOSE : PPSInterface::PPS_READ; - std::size_t nAddrPos = data.find(':'); - - if (nAddrPos != std::string::npos) { - - std::string sAddress = data.substr(nAddrPos+1); - std::size_t nAddrEnd = sAddress.find('\n'); - - if (nAddrEnd != std::string::npos) { - - sAddress = sAddress.substr(0, nAddrEnd); - - unsigned int interfaceId = 0; - - std::stringstream ss; - ss << sAddress; - ss >> interfaceId; - - PPSInterface* const pPPS = PPSInterface::getPPSInterface(interfaceId); - - if (pPPS) { - pPPS->onNotify(event); - } - } - } - - // Don't go off the end of the string - if (++nPos < data.length()) { - - // Remove the stuff up to the first '\n' and look for the next '\n' - data = data.substr(nPos); - nPos = data.find('\n'); - } - else { - - nPos = std::string::npos; - } - } - } -} - -} /* namespace jpps */ http://git-wip-us.apache.org/repos/asf/cordova-blackberry/blob/b3960ef0/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.h ---------------------------------------------------------------------- diff --git a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.h b/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.h deleted file mode 100644 index 143f052..0000000 --- a/blackberry10/bin/templates/project/plugins/JPPS/src/blackberry10/native/src/core/PPSNotifier.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2012 Research In Motion Limited. All rights reserved. - */ - -/* - * $QNXLicenseC: - * Copyright 2009, QNX Software Systems. All Rights Reserved. - * - * You must obtain a written license from and pay applicable license fees to QNX - * Software Systems before you may reproduce, modify or distribute this software, - * or any work that includes all or part of this software. Free development - * licenses are available for evaluation and non-commercial purposes. For more - * information visit http://licensing.qnx.com or email licensing@qnx.com. - * - * This file may contain contributions from others. Please review this entire - * file for other proprietary rights or license notices, as well as the QNX - * Development Suite License Guide at http://licensing.qnx.com/license-guide/ - * for other information. - * $ - */ - -#ifndef PPSNOTIFIER_H_ -#define PPSNOTIFIER_H_ - -#include - -#include "../utils/Thread.h" - -namespace jpps { - -/** - * PPSNotifier is an encapsulation of an open PPS .notify object. PPSNotifier has a - * blocking thread dedicated to reading from its .notify object. The thread constantly - * waits for new notifications in the .notify object. - * - * The way the PPS notify mechanism works is that on the first open/read of a .notify object, - * PPS provides a notify group id. This group id can be used when opening any PPS object to make - * the PPS object join the notify group. - * - * For example, you open a .notify file and the group id returned is "2a3". - * You subsequently open a PPS object and make it join that notify group: - * - * ::open("/pps/myppsobj?notify=2a3:someUniqueValueIDecide"); - * - * Now, every time myppsobj changes, the .notify file will be updated in the following manner: - * - * Notify 2a3:someUniqueValueIDecide - * - * For a change to the file. And - * - * -2a3:someUniqueValueIDecide - * - * if myppsobj is closed. - * - * When PPSNotifier reads a notification, the unique value is actually a unique identifier for a - * PPSInterface object that can be looked up in a global PPSInterface lookup table. Getting the - * PPSInterface object designated by the unique identifier, PPSNotifier calls PPSInterface::onNotify() - * to inform the PPSInterface object that there is new data pending or that the file has closed. - * It is then up to the PPSInterface to decide how to proceed to get that data from myppsobj. - */ -class PPSNotifier { - -public: - - /** - * Constructor. - */ - PPSNotifier(); - - /** - * Destructor. Note that this destructor will attempt to close the .notify - * object's file. - */ - virtual ~PPSNotifier(); - - /** - * Start the notify thread. - */ - void startNotifyLoop(); - - /** - * Get the .notify object's path. - * - * @return The path to the .notify object. - */ - inline std::string getNotifyObjPath() const { return m_notifyObjPath; } - - /** - * Set the .notify object's path. - * - * @param path The path of the .notify object (note that this should not include the - * .notify object name). - */ - inline void setNotifyOjbPath(const std::string& path) { m_notifyObjPath = path; } - - /** - * Get the .notify object's file descriptor. - * - * @return The file descriptor for the open .notify object. - */ - inline int getObjFd() const { return m_notifyObjFd; } - - /** - * Set the .notify object's file descriptor. - * - * @param The file descriptor for the open .notify object. - */ - inline void setObjFd(const int fd) { m_notifyObjFd = fd; } - - /** - * Set this notifier's .notify group ID (assigned by PPS). - * - * @param The .notify object's group ID, which is returned by PPS on the first read - * of the .notify object. - */ - inline std::string getNotifyGroupId() const { return m_notifyGroupId; } - - /** - * Get this notifier's .notify group ID (assigned by PPS). - * - * @return The .notify object's group ID. - */ - inline void setNotifyGroupId(const std::string& id) { m_notifyGroupId = id; } - -private: - - // Disable the copy constructor - PPSNotifier(const PPSNotifier& manager); - - // Disable the assignment operator - PPSNotifier& operator=(const PPSNotifier& rhs); - - /** - * Function used to start the thread. Pass this into the Thread::start() function. - * - * @param pArg A pointer to a PPSNotifier. - */ - static void* _notifyLoop(void* pArg); - - /** - * The main thread loop. Blocks on reading the .notify file. - */ - void notifyLoop(); - - /** The path of the .notify file we're monitoring to know when to get data. */ - std::string m_notifyObjPath; - - /** The file descriptor of the .notify file we're monitoring to know when to get data. */ - int m_notifyObjFd; - - /** The .notify group ID assigned by PPS when the group was created. */ - std::string m_notifyGroupId; - - /** The thread I'm running on. */ - Thread m_thread; -}; - -} /* namespace jpps */ -#endif /* PPSNOTIFIER_H_ */