/* * * Copyright (c) 1999 - 2011 my-Channels Ltd * Copyright (c) 2012 - 2017 Software AG, Darmstadt, Germany and/or Software AG USA Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors. * * Use, reproduction, transfer, publication or disclosure is prohibited except as specifically provided for in your License Agreement with Software AG. * */ #include "nSampleApp.h" #include "nDataGroupListener.h" #include "nDataStreamListener.h" #include "nSession.h" #include "nDataGroup.h" #include "nSecurityException.h" #include "nSessionNotConnectedException.h" #include "nUnexpectedResponseException.h" #include "nRequestTimedOutException.h" #include "nSessionPausedException.h" #include "nDataGroupDeletedException.h" #include "nSessionFactory.h" #include "nConsumeEvent.h" #include using namespace com::pcbsys::nirvana::client; using namespace com::pcbsys::nirvana::apps; class dataGroupsManager : nSampleApp, nDataGroupListener, nDataStreamListener { private: static dataGroupsManager *m_pSelf; std::map *m_pPropertiesDataGroups; std::map *m_pPropertiesDataStreams; std::map m_dataGroupsManager; void doit(std::string *pRealmDetails, int nRealmDetail, const std::string& propertiesFileGroup, const std::string& propertiesFileStreams, bool recreateGroups) { m_pSelf->constructSession(pRealmDetails, nRealmDetail, this); //Manages all data groups in a realm try { //Load the propertiesFile m_pPropertiesDataGroups = readPropertiesFile(propertiesFileGroup); m_pPropertiesDataStreams = readPropertiesFile(propertiesFileStreams); //Create all the data groups if requested if (recreateGroups) { std::list arr; for (std::map::iterator iterator = m_pPropertiesDataGroups->begin(); iterator != m_pPropertiesDataGroups->end(); iterator++) { if (iterator->first.compare("*") != 0) arr.push_back(iterator->first); } std::string *pArrS = new std::string[arr.size()]; int x = 0; for (std::list::iterator listIterator = arr.begin(); listIterator != arr.end(); listIterator++) { pArrS[x++] = *listIterator; } try { std::list *pDataGroups = m_pSession->getDataGroups(this); // Temporary kludge for (std::list::iterator iterator = pDataGroups->begin(); iterator != pDataGroups->end(); iterator++) { nDataGroup *pGroup = *iterator; if (pGroup->delRef()) delete pGroup; } delete pDataGroups; m_pSession->deleteDataGroup(pArrS, arr.size()); Poco::Thread::sleep(5000); m_pSession->createDataGroups(pArrS, arr.size()); } catch (Exception) { } } //Load up our data groups std::list *pAllDataGroup = m_pSession->getDataGroups(this); std::list::iterator groupIterator; for (groupIterator = pAllDataGroup->begin(); groupIterator != pAllDataGroup->end(); groupIterator++) { nDataGroup *pGroup = *groupIterator; m_dataGroupsManager.insert(std::map::value_type (pGroup->getName(), pGroup)); } //Setup all groups as per the propertiesDataGroups file for (groupIterator = pAllDataGroup->begin(); groupIterator != pAllDataGroup->end(); groupIterator++) { nDataGroup *pGroup = *groupIterator; configureGroup(pGroup); } //Setup all data streams as per the propertiesDataStream file std::list *pStreams = m_pSession->getDefaultDataGroup()->getStreams(); for (std::list::iterator streamIterator = pStreams->begin(); streamIterator != pStreams->end(); streamIterator++) { nDataStream *pStream = *streamIterator; configureStream(pStream); } // Manage groups and streams until the user presses a key printf("Press any key to quit !\n"); std::cin.ignore(); } catch (nSecurityException e) { printf("Insufficient permissions for the requested operation.\n"); printf("Please check the ACL settings on the server.\n"); exit(1); } catch (nSessionNotConnectedException snce) { printf("The session object used is not physically connected to the Nirvana realm.\n"); printf("Please ensure the realm is up and check your RNAME value.\n"); exit(1); } catch (nUnexpectedResponseException ure) { printf("The Nirvana REALM has returned an unexpected response.\n"); printf("Please ensure the Nirvana REALM and client API used are compatible.\n"); exit(1); } catch (nRequestTimedOutException rtoe) { printf("The requested operation has timed out waiting for a response from the REALM.\n"); printf("If this is a very busy REALM ask your administrator to increase the client timeout values.\n"); exit(1); } catch (nSessionPausedException e) { printf("Session has been paused, please resume the session\n"); exit(1); } catch (nDataGroupDeletedException e) { } //Close the session we opened try { nSessionFactory::close(m_pSession); } catch (Exception) { } //Close any other sessions within this JVM so that we can exit nSessionFactory::shutdown(); } /* * Configures the given group based on the props file */ private: void configureGroup(nDataGroup *pGrp) { //Check for wildcard adds addGroupToGroup("*", pGrp); //Check for specific group adds addGroupToGroup(pGrp->getName(), pGrp); } void addGroupToGroup(const std::string& subject, nDataGroup *pGroup) { //Check if there is any properties for this group std::string groupProperties = ""; std::map::iterator iterator = m_pPropertiesDataGroups->find (subject); if (iterator != m_pPropertiesDataGroups->end()) groupProperties = iterator->second; if (groupProperties.length() > 0) { int start = 0; while (true) { std::string groupProperty; int comma = groupProperties.find (',', start); if (comma == -1) groupProperty = groupProperties.substr(start); else groupProperty = groupProperties.substr(start, comma - start); //Check this is not a wild card of wildcards as that would have undefined and unwanted behaviour //If its just a wildcard add (group will have all groups under it) then continue if ((groupProperty.compare("*") == 0) && (subject.compare("*") != 0)) { for (std::map::iterator groupIterator = m_dataGroupsManager.begin(); groupIterator != m_dataGroupsManager.end(); groupIterator++) { nDataGroup *pAddGroup = groupIterator->second; try { if ((pAddGroup->getGroup(pGroup->getName()) == NULL) && (pAddGroup->getName().compare(pGroup->getName()) != 0)) { pGroup->add(pAddGroup); } else { printf("Can not add group %s to %s\n", pAddGroup->getName().c_str(), pGroup->getName().c_str()); } } catch (Exception e) { } } } else { //If its not a wild card then add the given property group to group try { // TODO: trim groupProperty nDataGroup *pAddGroup = NULL; std::map::iterator groupIterator = m_dataGroupsManager.find (groupProperty); if (groupIterator != m_dataGroupsManager.end()) pAddGroup = groupIterator->second; if (pAddGroup != NULL) { if ((pGroup->getName().compare(pAddGroup->getName()) != 0) && (pAddGroup->getGroup(pGroup->getName()) == NULL)) { pGroup->add(pAddGroup); } else { printf("Can not add group %s to %s\n", pAddGroup->getName().c_str(), pGroup->getName().c_str()); } } else { printf("Unknown Data Group: %s\n", groupProperty.c_str()); } } catch (Exception e) { } } if (comma == -1) break; start = comma + 1; } } } /* * Configure the given stream based on the property file */ private: void configureStream(nDataStream *pStream) { //Check for a global add addStreamsToGroups("*@*", pStream); //Check for specific add addStreamsToGroups(pStream->getSubject(), pStream); //Break the streams subject up so we can check for wildcard's int at = pStream->getSubject().find ('@'); std::string subject0; std::string subject1; if (at != -1) { subject0 = pStream->getSubject().substr(0, at); subject1 = pStream->getSubject().substr(at + 1); } subject0 += "@*"; subject1 = "*@" + subject1; //Check for a username at wildcard host addStreamsToGroups(subject0, pStream); //Check for wildcard username at specific host addStreamsToGroups(subject1, pStream); } void addStreamsToGroups(const std::string& subject, nDataStream *pStream) { std::string pds; std::map::iterator iterator = m_pPropertiesDataStreams->find (subject); if (iterator != m_pPropertiesDataStreams->end()) pds = iterator->second; if (pds.length() != 0) { int start = 0; while (true) { std::string tmp; int comma = pds.find (',', start); if (comma == -1) tmp = pds.substr(start); else tmp = pds.substr(start, comma - start); //Check for wildcard adds and if this is the case add this stream to all groups if (tmp.compare("*") == 0) { for (std::map::iterator groupIterator = m_dataGroupsManager.begin(); groupIterator != m_dataGroupsManager.end(); groupIterator++) { nDataGroup *pGrp = groupIterator->second; try { pGrp->add(pStream); } catch (Exception e) { } } } else { //If its not a wildcard at to all then just add this stream to the property files group // TODO: trim tmp nDataGroup *pGroup = NULL; std::map::iterator groupIterator = m_dataGroupsManager.find(tmp); if (groupIterator != m_dataGroupsManager.end()) pGroup = groupIterator->second; if (pGroup != NULL) { try { pGroup->add(pStream); } catch (Exception e) { } } } if (comma == -1) break; start = comma + 1; } } } protected: virtual void processArgs(int argc, char** argv) { if (argc < 5) { Usage(); exit(2); } } /** * Reads in a series of key value pairs from a properties file */ private: std::map* readPropertiesFile(const std::string& fileName) { std::map *pProps = new std::map(); try { FILE *pFile = fopen (fileName.c_str(), "r"); char buffer[256]; while (fgets (buffer, 256, pFile)) { strtok (buffer, "\n"); if ((buffer[0] == ';') || (buffer[0] == '#') || (buffer[0] == '\'')) continue; char *pKey = strtok (buffer, "="); char *pValue = strtok (NULL, "="); if (pValue == NULL) continue; // TODO: trim pKey and pValue if (((pValue[0] == '"') && (pValue[strlen(pValue) - 1] == '"')) || ((pValue[0] == '\'') && (pValue[strlen(pValue) - 1] == '\''))) { pValue++; pValue[strlen(pValue) - 1] = 0; } std::string key = pKey; std::string value = pValue; pProps->insert (std::map::value_type(key, value)); } fclose (pFile); } catch (Exception e) { printf("Error in properties file loading\n"); exit(1); } return pProps; } public: static int Main(int argc, char** argv) { //Create an instance for this class m_pSelf = new dataGroupsManager(); //Process command line arguments m_pSelf->processArgs(argc, argv); std::string autoRecreateStr = argv[4]; std::string propertiesFileStreams = argv[3]; std::string propertiesFileGroups = argv[2]; std::string RNAME = argv[1]; if ((propertiesFileGroups.length() < 1 ) || (propertiesFileStreams.length() < 1) || (autoRecreateStr.length() < 1) || (RNAME.length() < 1)) { Usage(); exit(1); } //Process Environment Variables nSampleApp::processEnvironmentVariables(); //Check the propertiesDataGroups file exists else create one FILE *pFile = fopen (propertiesFileGroups.c_str(), "r"); if (pFile) fclose (pFile); else { pFile = fopen (propertiesFileGroups.c_str(), "w+"); try { fprintf (pFile, "#This is the propertiesDataGroups file for sample dataGroupsManager data group mapping\n"); fprintf (pFile, "#This adds the data groups mentioned on the right of the equals sign to the data group mentioned on the left\n"); fprintf (pFile, "#dataGroupParent=dataGroupChild,dataGroupChild,dataGroupChild\n"); fclose (pFile); } catch (Exception e) { } } //Check the propertiesDataGroups file exists else create one pFile = fopen (propertiesFileStreams.c_str(), "r"); if (pFile) fclose (pFile); else { pFile = fopen (propertiesFileStreams.c_str(), "w+"); try { fprintf(pFile, "#This is the propertiesDataGroups file for sample dataGroupsManager data stream mapping\n"); fprintf(pFile, "#This adds streams based on subject on the left to groups on the right. The default one adds all streams to all groups\n"); fprintf(pFile, "#dataStreamSubject=dataGroupName,dataGroupName,dataGroupName\n"); fprintf(pFile, "*@*=*"); fclose (pFile); } catch (Exception e) { } } bool autoRecreate = false; if (autoRecreateStr.compare("true") == 0) autoRecreate = true; //Process the local REALM RNAME details int nRproperty = 0; std::string *pRproperties = parseRealmProperties(RNAME, nRproperty); //delete the data group specified m_pSelf->doit(pRproperties, nRproperty, propertiesFileGroups, propertiesFileStreams, autoRecreate); return 0; } /** * Prints the usage message for this class */ private: static void Usage() { printf("Usage ...\n\n"); printf("dataGroupsManager \n\n"); printf(" \n\n"); printf(" - the rname of the server to connect to\n"); printf(" - The location of the property file to use for mapping data groups to data groups\n"); printf(" - The location of the property file to use for mapping data streams to data groups\n"); printf(" - True or False to auto recreate data groups takes the data group property file and creates channels\n a group for every name mentioned on the left of equals sign\n"); printf("\n\nNote: -? provides help on environment variables \n\n"); } public: void addedStream(nDataGroup *pGroup, nDataStream *pStream, int count) { //If readonly then its the default data group so we want to process it if (pGroup->isReadOnly()) { configureStream(pStream); } else { printf("Added Stream %s to group %s\n", pStream->getName().c_str(), pGroup->getName().c_str()); } } void deletedStream(nDataGroup *pGroup, nDataStream *pStream, int count, bool serverRemoved) { printf("Deleted Stream %s from group %s server removed %d\n", pStream->getName().c_str(), pGroup->getName().c_str(), serverRemoved); } void createdGroup(nDataGroup *pGroup) { //When a group is created configure it if we have not already. nDataGroup *pGrp = NULL; std::map::iterator iterator = m_dataGroupsManager.find (pGroup->getName()); if (iterator != m_dataGroupsManager.end()) pGrp = iterator->second; if (pGrp == NULL) { m_dataGroupsManager.insert(std::map::value_type(pGroup->getName(), pGroup)); configureGroup(pGroup); printf("Created and Configured Group %s\n", pGroup->getName().c_str()); } else { printf("Already Had Created Group\n"); } } void deletedGroup(nDataGroup *pGroup) { //Remove the group as it no longer exists m_dataGroupsManager.erase(pGroup->getName()); printf("Deleted Group %s\n", pGroup->getName().c_str()); } void addedGroup(nDataGroup *pTo, nDataGroup *pGroup, int count) { printf("Added Group %s to %s\n", pGroup->getName().c_str(), pTo->getName().c_str()); } void removedGroup(nDataGroup *pFrom, nDataGroup *pGroup, int count) { printf("Removed Group %s from %s\n", pGroup->getName().c_str(), pFrom->getName().c_str()); } void onMessage(nConsumeEvent *pEvt) { printf("onMessage, event id : %lld\n", pEvt->getEventID()); if (pEvt->isEndOfChannel()) { printf("End of channel reached\n"); } //Print the message data if (pEvt->hasAttributes()) { displayEventAttributes(pEvt->getAttributes()); } nEventProperties *pProp = pEvt->getProperties(); if (pProp != NULL) { displayEventProperties(pProp); } printf("\n"); } dataGroupsManager() : m_pPropertiesDataGroups(NULL), m_pPropertiesDataStreams(NULL) { } }; dataGroupsManager* dataGroupsManager::m_pSelf = NULL; int main (int argc, char** argv) { return dataGroupsManager::Main (argc, argv); }