void MpCodecFactory::freeAllLoadedLibsAndCodec() { OsSharedLibMgrBase* pShrMgr = OsSharedLibMgr::getOsSharedLibMgr(); UtlHashBagIterator iter(mCodecsInfo); MpCodecSubInfo* pinfo; UtlHashBag libLoaded; UtlString* libName; while ((pinfo = (MpCodecSubInfo*)iter())) { if ((!pinfo->getCodecCall()->isStatic()) && (!libLoaded.find(&pinfo->getCodecCall()->getModuleName()))) { libLoaded.insert(const_cast<UtlString*>(&pinfo->getCodecCall()->getModuleName())); } } UtlHashBagIterator iter2(libLoaded); while ((libName = (UtlString*)iter2())) { pShrMgr->unloadSharedLib(libName->data()); } iter.reset(); while ((pinfo = (MpCodecSubInfo*)iter())) { if (!pinfo->getCodecCall()->isStatic()) { mCodecsInfo.remove(pinfo); delete pinfo; } } mCodecInfoCacheValid = FALSE; }
int MpTopologyGraph::addVirtualOutputs(MpResourceTopology& resourceTopology, UtlHashBag& newResources, UtlBoolean replaceNumInName, int resourceNum) { int portsAdded = 0; MpResourceTopology::VirtualPortIterator portIter; UtlString realResourceName; int realPortIdx; UtlString virtualResourceName; int virtualPortIdx; resourceTopology.initVirtualOutputIterator(portIter); while (resourceTopology.getNextVirtualOutput(portIter, realResourceName, realPortIdx, virtualResourceName, virtualPortIdx) == OS_SUCCESS) { if(replaceNumInName) { MpResourceTopology::replaceNumInName(realResourceName, resourceNum); MpResourceTopology::replaceNumInName(virtualResourceName, resourceNum); } // Lookup real resource. MpResource *pResource = (MpResource*)newResources.find(&realResourceName); assert(pResource); if (!pResource) { continue; } // Check port index correctness. Note, that this check gracefully // handles case with realPortIdx equal -1. if (realPortIdx >= pResource->maxOutputs()) { assert(!"Trying to map virtual port to non existing real port!"); continue; } // Add entry to virtual ports map. // We need to create UtlVoidPtr wrapper for pResource, or it will be // destroyed on pair deletion. UtlContainablePair *pRealPort = new UtlContainablePair(new UtlVoidPtr(pResource), new UtlInt(realPortIdx)); UtlContainablePair *pVirtPort = new UtlContainablePair(new UtlString(virtualResourceName), new UtlInt(virtualPortIdx)); mVirtualOutputs.insertKeyAndValue(pVirtPort, pRealPort); portsAdded++; } resourceTopology.freeVirtualOutputIterator(portIter); return portsAdded; }
void testRemoveReference() { // the following two entries collide if the initial bucket size is 16 UtlInt int1(1); UtlInt int16(16); UtlInt int2a(2); UtlInt int2b(2); UtlInt int3(3); UtlHashBag bag; CPPUNIT_ASSERT( bag.numberOfBuckets() == 16 ); // check assumption of collision // Load all the test objects CPPUNIT_ASSERT( bag.insert(&int1) == &int1 ); CPPUNIT_ASSERT( bag.insert(&int16) == &int16 ); CPPUNIT_ASSERT( bag.insert(&int2a) == &int2a ); CPPUNIT_ASSERT( bag.insert(&int2b) == &int2b ); CPPUNIT_ASSERT( bag.insert(&int3) == &int3 ); // Check that everything is there CPPUNIT_ASSERT( bag.entries() == 5 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( bag.contains(&int16) ); CPPUNIT_ASSERT( bag.contains(&int2a) ); // cannot test for 2a and 2b independently CPPUNIT_ASSERT( bag.contains(&int3) ); // Take entry 1 out (might collide w/ 16) CPPUNIT_ASSERT( bag.removeReference(&int1) == &int1 ); // Check that everything except entry 1 is still there, and that 1 is gone CPPUNIT_ASSERT( bag.entries() == 4 ); CPPUNIT_ASSERT( ! bag.contains(&int1) ); CPPUNIT_ASSERT( bag.contains(&int16) ); CPPUNIT_ASSERT( bag.contains(&int2a) );// cannot test for 2a and 2b independently CPPUNIT_ASSERT( bag.contains(&int3) ); // Put entry 1 back in (so that 16 will collide w/ it again) CPPUNIT_ASSERT( bag.insert(&int1) == &int1 ); // Check that everything is there CPPUNIT_ASSERT( bag.entries() == 5 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( bag.contains(&int16) ); CPPUNIT_ASSERT( bag.contains(&int2a) ); CPPUNIT_ASSERT( bag.contains(&int3) ); // Take entry 16 out (might collide w/ 1) CPPUNIT_ASSERT( bag.removeReference(&int16) == &int16 ); // Check that everything except entry 16 is still there, and that 16 is gone CPPUNIT_ASSERT( bag.entries() == 4 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( ! bag.contains(&int16) ); CPPUNIT_ASSERT( bag.contains(&int2a) );// cannot test for 2a and 2b independently CPPUNIT_ASSERT( bag.contains(&int3) ); // remove 2a (and ensure that you don't get back 2b) CPPUNIT_ASSERT( bag.removeReference(&int2a) == &int2a ); // Check that everything that should be is still there CPPUNIT_ASSERT( bag.entries() == 3 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( ! bag.contains(&int16) ); CPPUNIT_ASSERT( bag.find(&int2a) == &int2b ); // equal values, but now there's only one CPPUNIT_ASSERT( bag.contains(&int3) ); // remove 3 (no collision for this one) CPPUNIT_ASSERT( bag.removeReference(&int3) == &int3 ); // Check that everything that should be is still there CPPUNIT_ASSERT( bag.entries() == 2 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( ! bag.contains(&int16) ); CPPUNIT_ASSERT( bag.find(&int2a) == &int2b ); // equal values, but now there's only one CPPUNIT_ASSERT( ! bag.contains(&int3) ); // remove 3 again - should fail this time CPPUNIT_ASSERT( bag.removeReference(&int3) == NULL ); // Check that everything that should be is still there CPPUNIT_ASSERT( bag.entries() == 2 ); CPPUNIT_ASSERT( bag.contains(&int1) ); CPPUNIT_ASSERT( ! bag.contains(&int16) ); CPPUNIT_ASSERT( bag.find(&int2a) == &int2b ); // equal values, but now there's only one CPPUNIT_ASSERT( ! bag.contains(&int3) ); }
/*!a Test case to test the destroy() * method. */ void testRemoveAndDestroy() { const char* prefix = "test the destroy() method " ; // The ContainableTestStub has been implemented such that a static // counter is incremented everytime an instance is created and // the counter is decremented everytime an instance is destroyed. UtlContainableTestStub* uStub = new UtlContainableTestStub(0) ; UtlContainableTestStub* uStubPtr = new UtlContainableTestStub(101) ; commonList.insert(uStub) ; commonList.insert(uStubPtr) ; string msg ; int cCountBefore = UtlContainableTestStub :: getCount() ; UtlBoolean retValue = commonList.destroy(uStubPtr) ; int cCountAfter ; uStubPtr = NULL ; TestUtilities::createMessage(2, &msg, prefix, ":- Verify the return value") ; CPPUNIT_ASSERT_MESSAGE(msg.data(), retValue) ; // To verify that the object was destroyed, check to see if the static count has been // decremented. If yes, it means that the destructor was called. cCountAfter = UtlContainableTestStub :: getCount() ; TestUtilities::createMessage(2, &msg, prefix, ":- Verify that the object was deleted") ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), cCountBefore -1, cCountAfter) ; // THe way to verify if the object has been removed is to // create a new stub such that it has the same value as // the removed stub. Try to find the new stub UtlContainableTestStub uStubNew(101) ; UtlContainable* uSearch = commonList.find(&uStubNew) ; TestUtilities::createMessage(2, &msg, prefix, ":- Verify that the entry is removed") ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), (void*)NULL, (void*)uSearch) ; // Now test the case when you have added multiple deletable keys // and the first key inserted is deleted first. UtlContainableTestStub* uStubPtr2 = new UtlContainableTestStub(201) ; UtlContainableTestStub* uStubPtr3 = new UtlContainableTestStub(201) ; commonList.insert(uStubPtr2) ; commonList.insert(uStubPtr3) ; UtlInt uTestInt(2031) ; commonList.insert(&uTestInt) ; // after destroying, either uStubPtr or uStubPtr3 might have gotten deleted and // we have no way to find out which one. So create a new ContainableTestStub // and use that for search UtlContainableTestStub uStubTemp(201) ; cCountBefore = UtlContainableTestStub :: getCount() ; commonList.destroy(&uStubTemp) ; cCountAfter = UtlContainableTestStub :: getCount() ; uSearch = commonList.find(&uStubTemp) ; const char* msgTemp = "Verify that doing a removeAndDestroy on " \ "an item that has multiple matches removes only one entry " ; TestUtilities::createMessage(2, &msg, msgTemp, " :- Verify value is still found") ; CPPUNIT_ASSERT_MESSAGE("Verify that doing a removeAndDestroy on " \ "an item that has multiple matches removes only one entry", \ uSearch == uStubPtr2 || uSearch == uStubPtr3) ; TestUtilities::createMessage(2, &msg, msgTemp, " :- Verify value *was* destroyed") ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), cCountBefore -1, cCountAfter) ; msgTemp = "Verify that the remaining entry can also be deleted" ; cCountBefore = UtlContainableTestStub :: getCount() ; commonList.destroy(&uStubTemp) ; cCountAfter = UtlContainableTestStub :: getCount() ; TestUtilities::createMessage(2, &msg, msgTemp, " :- Verify value *was* destroyed") ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), cCountBefore -1, cCountAfter) ; // In all the above tests, a total of 5 entries were added // and 3 were removed. int finalCount = commonEntriesCount + 2 ; msgTemp = "Verify that the HashTable stil has the other entries" ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msgTemp, finalCount, (int)commonList.entries()) ; }
void utlTestFind_And_Contains(FindOrContains type) { const int testCount = 7 ; const char* prefixFind = "Test the find() method when the match " ; const char* prefixContains = "Test the contains() method when the match " ; const char* Msgs[] = { \ "is the first element ", \ "is the last element ", \ "is a mid element (unique match) ", \ "has two value matches but a single ref match ", \ "has two ref matches", \ "has a value match but no ref match", \ "has no match at all" \ } ; // insert two elements to satisfy (d) and (e) commonList.insert( commonContainables_Clone[4]) ; commonList.insert( commonContainables[3]) ; UtlString noExist("This cannot and should not exist!!!") ; UtlContainable* searchValues[] = { \ commonContainables[0], commonContainables[5], commonContainables[2], \ commonContainables[4], commonContainables[3], \ commonContainables_Clone[2], &noExist \ } ; bool expectedValues_Contains[] = {true, true, true, true, true, true, false } ; UtlContainable* searchValuesForFind[] = { \ commonContainables[0], commonContainables[5], commonContainables[2], \ commonContainables[4], commonContainables[3], \ commonContainables_Clone[1], &noExist \ } ; // In case of the hashtable, searching for a key can return *ANY* of the values // that matches and we dont care about which one. so we need two set of expected values UtlContainable* expValues_Find[][2] = { \ {commonContainables[0], commonContainables[0]}, \ {commonContainables[5], commonContainables[2]}, \ {commonContainables[2], commonContainables[2]}, \ {commonContainables_Clone[4], commonContainables[4]}, \ {commonContainables[3], commonContainables[3]}, \ {commonContainables[1], commonContainables[1]}, \ {NULL, NULL} \ } ; for (int i = 0 ; i < testCount ; i++) { string msg ; if (type == TEST_FIND) { bool isFound = false ; UtlContainable* act = commonList.find(searchValuesForFind[i]) ; // If we are expecting either 'A' or 'B' for the search isFound = (act == expValues_Find[i][0]) || (act == expValues_Find[i][1]) ; TestUtilities::createMessage(2, &msg, prefixFind, Msgs[i]) ; CPPUNIT_ASSERT_MESSAGE(msg.data(), isFound) ; } else if (type == TEST_CONTAINS) { UtlBoolean act = commonList.contains(searchValues[i]) ; UtlBoolean exp = (UtlBoolean)expectedValues_Contains[i] ; TestUtilities::createMessage(2, &msg, prefixContains, Msgs[i]) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), exp, act) ; } } }//utlTestIndex
/*a! Test the insert method for a list that is not empty. Add both unique and non-unique entries. * * The test data for this test is :- * a) Add a new UtlInt * b) Add a new UtlString * c) Add a new UtlVoidPtr * d) Add a new Containable such that a similar one (value match) exists already * e) Add a new Containable such that the same one (reference match) exists already */ void testInsert() { struct testInsertStructure { const char* testDescription ; UtlContainable* itemToAdd ; UtlContainable* expectedReturnValue ; // In case of the hashtable, searching for a key can return *ANY* of the values // that matches and we dont care about which one. so we need two set of expected values UtlContainable* expectedFoundValue ; UtlContainable* altExpectedFoundValue ; } ; const char* prefix = "Test the insert(UtlContainable*) method for a non empty HashTable " ; const char* suffix1 = " :- Verify return value" ; const char* suffix2 = " :- Verify that the value is inserted" ; const char* suffix3 = " :- Verify that the number of entries is incremented by one" ; UtlInt uInt = UtlInt(1234) ; UtlString uString = UtlString("Test String") ; UtlVoidPtr uVoidPtr((char*)"Hello world") ; testInsertStructure testData[] = { \ { "Add a new UtlInt ", &uInt, &uInt, &uInt, &uInt}, \ { "Add a new UtlString ", &uString, &uString, &uString, &uString}, \ { "Add a new UtlVoidPtr ", &uVoidPtr, &uVoidPtr, &uVoidPtr, &uVoidPtr}, \ { "Add a Containable such that an identical one(value match) " \ "exists in the table ", commonContainables_Clone[3], commonContainables_Clone[3], \ commonContainables[3], commonContainables_Clone[3] }, \ { "Add a Containable such that an exact duplicate " \ "(including reference match) exists in the table ", commonContainables[4], commonContainables[4], commonContainables[4] } \ } ; int expCount = commonEntriesCount; string msg ; UtlContainable* uAct ; UtlContainable* uReturn ; /* :TODO: this part of the test is in error. * when there is more than one of the same value in the bage, * the find() method may return any of the objects with that value. */ int testCount = sizeof(testData)/sizeof(testData[0]) ; for (int i = 0 ; i < testCount ; i++) { uReturn = commonList.insert(testData[i].itemToAdd) ; expCount++ ; uAct = commonList.find(testData[i].itemToAdd) ; TestUtilities::createMessage(3, &msg, prefix, \ testData[i].testDescription, suffix1) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), \ testData[i].expectedReturnValue, uReturn) ; // when there is more than one of the same value in the bag, // the find() method may return any of the objects with that value. bool isFound = (uAct == testData[i].expectedFoundValue) || \ (uAct == testData[i].altExpectedFoundValue) ; TestUtilities::createMessage(3, &msg, prefix, \ testData[i].testDescription, suffix2) ; CPPUNIT_ASSERT_MESSAGE(msg.data(), isFound) ; TestUtilities::createMessage(3, &msg, prefix, \ testData[i].testDescription, suffix3) ; CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.data(), expCount, (int)commonList.entries()) ; } } //testInsert
int MpTopologyGraph::linkTopologyResources(MpResourceTopology& resourceTopology, UtlHashBag& newResources, UtlBoolean replaceNumInName, int resourceNum) { // Link the resources int connectionIndex = 0; UtlString outputResourceName; UtlString inputResourceName; int outputResourcePortIndex; int inputResourcePortIndex; MpResource* outputResource = NULL; MpResource* inputResource = NULL; OsStatus result; UtlHashMap newConnectionIds; #ifdef TEST_PRINT osPrintf("%d new resources in the list\n", newResources.entries()); UtlHashBagIterator iterator(newResources); MpResource* containerResource = NULL; while(containerResource = (MpResource*) iterator()) { osPrintf("found list resource: \"%s\" value: \"%s\"\n", containerResource->getName().data(), containerResource->data()); } #endif while(resourceTopology.getConnection(connectionIndex, outputResourceName, outputResourcePortIndex, inputResourceName, inputResourcePortIndex) == OS_SUCCESS) { if(replaceNumInName) { resourceTopology.replaceNumInName(outputResourceName, resourceNum); resourceTopology.replaceNumInName(inputResourceName, resourceNum); } // Look in the container of new resources first as this is more // efficient and new resources are not added immediately to a running // flowgraph outputResource = (MpResource*) newResources.find(&outputResourceName); if(outputResource == NULL) { result = lookupResource(outputResourceName, outputResource); if(result != OS_SUCCESS) { int virtPortIdx = outputResourcePortIndex>=0?outputResourcePortIndex:-1; int realPortIdx; result = lookupVirtualOutput(outputResourceName, virtPortIdx, outputResource, realPortIdx); if (result == OS_SUCCESS && outputResourcePortIndex>=0) { outputResourcePortIndex = realPortIdx; } } assert(result == OS_SUCCESS); } inputResource = (MpResource*) newResources.find(&inputResourceName); if(inputResource == NULL) { result = lookupResource(inputResourceName, inputResource); if(result != OS_SUCCESS) { int virtPortIdx = inputResourcePortIndex>=0?inputResourcePortIndex:-1; int realPortIdx; result = lookupVirtualInput(inputResourceName, virtPortIdx, inputResource, realPortIdx); if (result == OS_SUCCESS && inputResourcePortIndex>=0) { inputResourcePortIndex = realPortIdx; } } assert(result == OS_SUCCESS); } assert(outputResource); assert(inputResource); if(outputResource && inputResource) { if(outputResourcePortIndex == MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT) { outputResourcePortIndex = outputResource->reserveFirstUnconnectedOutput(); assert(outputResourcePortIndex >= 0); } else if(outputResourcePortIndex < MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT) { // First see if a real port is already in the dictionary UtlInt searchKey(outputResourcePortIndex); UtlInt* foundValue = NULL; if((foundValue = (UtlInt*) newConnectionIds.findValue(&searchKey))) { // Use the mapped index outputResourcePortIndex = foundValue->getValue(); } else { // Find an available port and add it to the map int realPortNum = outputResource->reserveFirstUnconnectedOutput(); assert(realPortNum >= 0); UtlInt* portKey = new UtlInt(outputResourcePortIndex); UtlInt* portValue = new UtlInt(realPortNum); newConnectionIds.insertKeyAndValue(portKey, portValue); outputResourcePortIndex = realPortNum; } } if(inputResourcePortIndex == MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT) { inputResourcePortIndex = inputResource->reserveFirstUnconnectedInput(); assert(inputResourcePortIndex >= 0); } else if(inputResourcePortIndex < MpResourceTopology::MP_TOPOLOGY_NEXT_AVAILABLE_PORT) { // First see if a real port is already in the dictionary UtlInt searchKey(inputResourcePortIndex); UtlInt* foundValue = NULL; if((foundValue = (UtlInt*) newConnectionIds.findValue(&searchKey))) { // Use the mapped index inputResourcePortIndex = foundValue->getValue(); } else { // Find an available port and add it to the map int realPortNum = inputResource->reserveFirstUnconnectedInput(); assert(realPortNum >= 0); UtlInt* portKey = new UtlInt(inputResourcePortIndex); UtlInt* portValue = new UtlInt(realPortNum); newConnectionIds.insertKeyAndValue(portKey, portValue); inputResourcePortIndex = realPortNum; } } result = addLink(*outputResource, outputResourcePortIndex, *inputResource, inputResourcePortIndex); assert(result == OS_SUCCESS); } connectionIndex++; } newConnectionIds.destroyAll(); return(connectionIndex); }
void SipPublishContentMgr::getPublished(const char* resourceId, const char* eventTypeKey, UtlBoolean fullState, int& numContentTypes, HttpBody**& eventContent, SipPublishContentMgrDefaultConstructor** pDefaultConstructor) { // Construct the key to look up. UtlString key; key.append(resourceId); key.append(CONTENT_KEY_SEPARATOR); key.append(eventTypeKey); lock(); // Look up the key in the specific or default entries, as appropriate. UtlHashBag* bag = resourceId ? (fullState ? &mContentEntries : &mPartialContentEntries) : (fullState ? &mDefaultContentEntries : &mDefaultPartialContentEntries); PublishContentContainer* container = dynamic_cast <PublishContentContainer*> (bag->find(&key)); // If not found, return zero versions. if (container == NULL) { numContentTypes = 0; eventContent = new HttpBody*[0]; } // Content for this event type exists. else { int num = container->mEventContent.entries(); numContentTypes = num; HttpBody** contentCopies = new HttpBody*[num]; eventContent = contentCopies; // Copy the contents into the array. for (int index = 0; index < num; index++) { eventContent[index] = new HttpBody(*dynamic_cast <HttpBody*> (container->mEventContent.at(index))); } } // Return the default constructor, if any. if (pDefaultConstructor && !resourceId) { UtlContainable* defaultConstructor = (fullState ? mDefaultContentConstructors : mDefaultPartialContentConstructors).findValue(&key); *pDefaultConstructor = // Is there a default constructor? defaultConstructor ? // If so, make a copy of the constructor and return pointer to it. (dynamic_cast <SipPublishContentMgrDefaultConstructor*> (defaultConstructor))->copy() : // Otherwise, return NULL. NULL; } unlock(); return; }
UtlBoolean SipPublishContentMgr::getContent(const char* resourceId, const char* eventTypeKey, const char* eventType, UtlBoolean fullState, const UtlString& acceptHeaderValue, HttpBody*& content, UtlBoolean& isDefaultContent, UtlString* availableMediaTypes) { UtlBoolean foundContent = FALSE; PublishContentContainer* container = NULL; isDefaultContent = FALSE; UtlString key; key.append(resourceId); key.append(CONTENT_KEY_SEPARATOR); key.append(eventTypeKey); lock(); UtlHashBag* pContent; if (fullState) { // Full content (this is the usual case) pContent = &mContentEntries; } else { // Partial content (used for partial dialog events) pContent = &mPartialContentEntries; } // See if resource-specific content exists container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // There is no resource-specific content. Check if the default // constructor exists. if (container == NULL) { // Construct the key for the default data. UtlString default_key; default_key.append(CONTENT_KEY_SEPARATOR); default_key.append(eventTypeKey); // Look up the constructor. UtlHashMap* pDefaultConstructors; if (fullState) { // Full content (this is the usual case) pDefaultConstructors = &mDefaultContentConstructors; } else { // Partial content (used for partial dialog events) pDefaultConstructors = &mDefaultPartialContentConstructors; } SipPublishContentMgrDefaultConstructor* constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (pDefaultConstructors->findValue(&default_key)); // If it exists, call it to publish content for this resource/event. if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // See if resource-specific content exists now. container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If content was found, still mark it as default content. if (container) { isDefaultContent = TRUE; } // If still no content was found, check if (fixed) default content exists. else { container = dynamic_cast <PublishContentContainer*> (mDefaultContentEntries.find(&default_key)); if(container) { isDefaultContent = TRUE; } } } // Within the container, choose the correct content. if (container) { if (acceptHeaderValue.compareTo(acceptAllTypes) != 0) { // Search for the first content in the container whose // MIME type is in the acceptable list. UtlSListIterator contentIterator(container->mEventContent); HttpBody* bodyPtr; while (!foundContent && (bodyPtr = dynamic_cast <HttpBody*> (contentIterator()))) { // Trim any parameters off the body content type. UtlString* content_type = bodyPtr; UtlString base_content_type(*content_type); ssize_t i = base_content_type.index(';'); if (i != UTL_NOT_FOUND) { base_content_type.remove(i); } // See if base_content_type is in acceptHeaderValue. if (acceptHeaderValue.findToken(base_content_type.data(), ",", ";")) { // If base_content_type is "multipart/related", extract // the 'type' parameter value, which is the type of the // root component, and check whether it is in acceptHeaderValue. ssize_t j; if (base_content_type.compareTo("multipart/related", UtlString::ignoreCase) == 0) { // Search for the 'type' parameter. i = content_type->index(";type=", UtlString::ignoreCase); if (i != UTL_NOT_FOUND) { // Advance i to point to the value. i += sizeof (";type=") - 1; if ((*content_type)(i) == '\"') { // Value is quoted. // Advance i to point to the value proper. i++; // Find the closing double-quote. j = content_type->index('\"', i); if (j == UTL_NOT_FOUND) { // This shouldn't happen. Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent " "No closing double-quote found for 'type' parameter in body MIME type '%s'", content_type->data()); // j == UTL_NOT_FOUND indicates failure. } } else { // Value is not quoted. // Find the end of the parameter. j = content_type->index(';', i); if (j == UTL_NOT_FOUND) { j = content_type->length(); } } if (j != UTL_NOT_FOUND) { // Characters from i to j are the type parameter value. UtlString base_root_type; base_root_type.append(*content_type, i, j - i); // Remove parameters from base_root_type. ssize_t k = base_content_type.index(';'); if (k != UTL_NOT_FOUND) { base_content_type.remove(k); } // See if base_root_type is in acceptHeaderValue. if (acceptHeaderValue.findToken(base_root_type.data(), ",", ";")) { // Having passed all the tests, this content is OK. foundContent = true; } } } else { Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent " "No 'type' parameter in body MIME type '%s'", content_type->data()); } } else { // If base_content_type is not multipart/related, // we can accept the content with no further tests. foundContent = true; } // If this content is acceptable, copy it into 'content'. // Because foundContent is true, the loop will exit. if (foundContent) { content = bodyPtr->copy(); } } } if (!foundContent) { // No content was found that matched the allowed MIME types. Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no acceptable content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType); if (availableMediaTypes) { // Construct the list of available MIME types. availableMediaTypes->remove(0); contentIterator.reset(); while ((bodyPtr = dynamic_cast <HttpBody*> (contentIterator()))) { if (!availableMediaTypes->isNull()) { availableMediaTypes->append(','); } availableMediaTypes->append(static_cast <UtlString&> (*bodyPtr)); } } } } else { // No MIME types were specified, take the first content in the list. // (which should exist) HttpBody* bodyPtr = dynamic_cast <HttpBody*> (container->mEventContent.first()); if (bodyPtr) { content = bodyPtr->copy(); foundContent = TRUE; } else { // No content was found (at all). // Set *availableMediaTypes. if (availableMediaTypes) { availableMediaTypes->remove(0); } Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s' - publish() must have been called with numContentTypes==0", key.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } } else { // No container found for this resource and event. // Set *availableMediaTypes. if (availableMediaTypes) { availableMediaTypes->remove(0); } Os::Logger::instance().log(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no container found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s', fullState = %d", key.data(), acceptHeaderValue.data(), resourceId ? resourceId : "[none]", eventTypeKey, eventType, fullState); } unlock(); return foundContent; }
void SipPublishContentMgr::publish(const char* resourceId, const char* eventTypeKey, const char* eventType, int numContentTypes, HttpBody* eventContent[], UtlBoolean fullState, UtlBoolean noNotify) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipPublishContentMgr::publish resourceId '%s', eventTypeKey '%s', eventType '%s', numContentTypes %d, noNotify %d, fullState %d", resourceId ? resourceId : "(null)", eventTypeKey, eventType, numContentTypes, noNotify, fullState); if (numContentTypes < 1) { Os::Logger::instance().log(FAC_SIP, PRI_ERR, "SipPublishContentMgr::publish " "No content bodies supplied for resourceId '%s', " "eventTypeKey '%s', fullState %d", resourceId? resourceId : "(null)", eventTypeKey, fullState); } // Construct the key to look up. UtlString key; key.append(resourceId); key.append(CONTENT_KEY_SEPARATOR); key.append(eventTypeKey); lock(); // Determine the storage we will be using. UtlHashBag* pContent; // resourceId can be NULL if we are called from ::publishDefault() if (resourceId) { if (fullState) { // Full dialog events pContent = &mContentEntries; } else { // Partial dialog events pContent = &mPartialContentEntries; } } else { // Default dialog events if (fullState) { pContent = &mDefaultContentEntries; } else { pContent = &mDefaultPartialContentEntries; } } // Look up the key in the specific or default entries, as appropriate. PublishContentContainer* container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If not found, create a container. if (container == NULL) { container = new PublishContentContainer(key); // Save the container in the appropriate hash. pContent->insert(container); } // The content for this event type already existed else { // Remove the old content container->mEventContent.destroyAll(); } // Add the new content for (int index = 0; index < numContentTypes; index++) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipPublishContentMgr::publish eventContent[%d] = %p, key = '%s', content type = '%s', getBytes() = %p '%s'", index, eventContent[index], key.data(), eventContent[index]->data(), eventContent[index]->getBytes(), eventContent[index]->getBytes()); container->mEventContent.append(eventContent[index]); } // Don't call the observers if noNotify is set or if this is default content. if (!noNotify && resourceId) { // Call the observer for the content change, if any. UtlString eventTypeString(eventType); PublishCallbackContainer* callbackContainer = dynamic_cast <PublishCallbackContainer*> (mEventContentCallbacks.find(&eventTypeString)); if (callbackContainer) { (callbackContainer->mpCallback)(callbackContainer->mpApplicationData, resourceId, eventTypeKey, eventTypeString, NULL); } } unlock(); }
UtlBoolean SipPublishContentMgr::getContent(const char* resourceId, const char* eventTypeKey, const char* eventType, const char* acceptHeaderValue, HttpBody*& content, int& version, UtlBoolean& isDefaultContent, UtlBoolean fullState) { UtlBoolean foundContent = FALSE; UtlString key(resourceId); key.append(eventTypeKey); PublishContentContainer* container = NULL; isDefaultContent = FALSE; // Turn acceptHeaderValue into a HashBag of its components. // acceptedTypesGiven = FALSE if there are no components. UtlHashBag contentTypes; UtlBoolean acceptedTypesGiven = buildContentTypesContainer(acceptHeaderValue, contentTypes); lock(); UtlHashBag* pContent; if (fullState) { // Full content (this is the usual case) pContent = &mContentEntries; } else { // Partial content (used for partial dialog events) pContent = &mPartialContentEntries; } // See if resource-specific content exists container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // There is no resource-specific content. Check if the default // constructor exists. if (container == NULL) { // Construct the key for the default data. UtlString default_key(eventTypeKey); // Look up the constructor. SipPublishContentMgrDefaultConstructor* constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (mDefaultContentConstructors.findValue(&default_key)); // If it exists, call it to publish content for this resource/event. if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // See if resource specific content exists now. container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If content was found, still mark it as default content. if (container) { isDefaultContent = TRUE; } // If still no content was found, check if the default exists. else { container = dynamic_cast <PublishContentContainer*> (mDefaultContentEntries.find(&default_key)); if(container) { isDefaultContent = TRUE; } } } // Within the container, find the content of the right MIME type. if (container) { if (acceptedTypesGiven) { UtlString base_mime_type; // Search for the first content in the container whose // MIME type is in the acceptable list. UtlSListIterator contentIterator(container->mEventContent); HttpBody* bodyPtr; UtlSListIterator versionIterator(container->mEventVersion); UtlInt* versionPtr; while (!foundContent && (bodyPtr = dynamic_cast <HttpBody*> (contentIterator())) && (versionPtr = dynamic_cast <UtlInt*> (versionIterator()))) { // Test if ';' is present in *bodyPtr's MIME type. // (Remember that an HttpBody considered as a UtlString has // the value of its content type.) ssize_t i = bodyPtr->index(';'); // The 'if expression' is TRUE if the MIME type of *bodyPtr // is found in in contentTypes. This is messy, because // *bodyPtr's MIME type may have parameters, which have // to be removed before searching contentTypes. if (contentTypes.find(i == UTL_NOT_FOUND ? bodyPtr : ( base_mime_type.remove(0), base_mime_type.append(*bodyPtr, 0, i), &base_mime_type))) { content = bodyPtr->copy(); version = versionPtr->getValue(); foundContent = TRUE; } } if (!foundContent) { // No content was found that matched the required MIME types. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } else { // No MIME types were specified, take the first content in the list. HttpBody* bodyPtr = dynamic_cast <HttpBody*> (container->mEventContent.first()); UtlInt* versionPtr = dynamic_cast <UtlInt*> (container->mEventVersion.first()); if (bodyPtr) { content = bodyPtr->copy(); version = versionPtr->getValue(); foundContent = TRUE; } else { // No content was found (at all). OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no content found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s'", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType); } } } else { // No container found for this resource and event. OsSysLog::add(FAC_SIP, PRI_WARNING, "SipPublishContentMgr::getContent no container found for key '%s', acceptHeaderValue '%s', resourceId '%s', eventTypeKey ='%s', eventType '%s', fullState = %d", key.data(), acceptHeaderValue ? acceptHeaderValue : "[none]", resourceId ? resourceId : "[none]", eventTypeKey, eventType, fullState); } unlock(); contentTypes.destroyAll(); return (foundContent); }
void SipPublishContentMgr::publish(const char* resourceId, const char* eventTypeKey, const char* eventType, int numContentTypes, HttpBody* eventContent[], const int eventVersion[], UtlBoolean noNotify, UtlBoolean fullState) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPublishContentMgr::publish resourceId '%s', eventTypeKey '%s', eventType '%s', numContentTypes %d, noNotify %d, fullState %d", resourceId, eventTypeKey, eventType, numContentTypes, noNotify, fullState); UtlBoolean resourceIdProvided = resourceId && *resourceId; // Construct the key to look up. UtlString key; if(resourceIdProvided) { key = resourceId; } if(eventTypeKey) { key.append(eventTypeKey); } lock(); // Determine the type of storage we will be using UtlHashBag* pContent; if (resourceIdProvided) { if (fullState) { // Full dialog events pContent = &mContentEntries; } else { // Partial dialog events pContent = &mPartialContentEntries; } } else { // Default dialog events pContent = &mDefaultContentEntries; } // Look up the key in the specific or default entries, as appropriate. PublishContentContainer* container = dynamic_cast <PublishContentContainer*> (pContent->find(&key)); // If not found, create a container. if(container == NULL) { container = new PublishContentContainer(); *((UtlString*) container) = key; // Save the container in the appropriate hash. pContent->insert(container); } // The content for this event type already existed else { // Remove the old content container->mEventContent.destroyAll(); container->mEventVersion.destroyAll(); } // Add the new content for (int index = 0; index < numContentTypes; index++) { OsSysLog::add(FAC_SIP, PRI_DEBUG, "SipPublishContentMgr::publish eventContent[%d] = %p, key = '%s', content type = '%s', version = %d, getBytes() = %p '%s'", index, eventContent[index], key.data(), eventContent[index]->data(), eventVersion[index], eventContent[index]->getBytes(), eventContent[index]->getBytes()); container->mEventContent.append(eventContent[index]); container->mEventVersion.append(new UtlInt(eventVersion[index])); } // Don't call the observers if noNotify is set or if this is default content. if (!noNotify && resourceIdProvided) { // Call the observer for the content change, if any. UtlString eventTypeString(eventType); PublishCallbackContainer* callbackContainer = dynamic_cast <PublishCallbackContainer*> (mEventContentCallbacks.find(&eventTypeString)); if(callbackContainer && callbackContainer->mpCallback) { (callbackContainer->mpCallback)(callbackContainer->mpApplicationData, resourceId, eventTypeKey, eventTypeString); } } unlock(); }