void SipPublishContentMgr::unpublish(const char* resourceId, const char* eventTypeKey, const char* eventType, const char* reason) { Os::Logger::instance().log(FAC_SIP, PRI_DEBUG, "SipPublishContentMgr::unpublish resourceId '%s', eventTypeKey '%s', eventType '%s', reason '%s'", resourceId ? resourceId : "(null)", eventTypeKey, eventType, reason ? reason : "(null)"); // 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. if (resourceId) { PublishContentContainer* content = dynamic_cast <PublishContentContainer*> (mContentEntries.remove(&key)); PublishContentContainer* partialContent = dynamic_cast <PublishContentContainer*> (mPartialContentEntries.remove(&key)); // Call the default content constructors, if available. // Construct the key for the default data. UtlString default_key; default_key.append(CONTENT_KEY_SEPARATOR); default_key.append(eventTypeKey); // If it exists, call it to publish full content for this resource/event. SipPublishContentMgrDefaultConstructor* constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (mDefaultContentConstructors.findValue(&default_key)); if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // If it exists, call it to publish partial content for this resource/event. constructor = dynamic_cast <SipPublishContentMgrDefaultConstructor*> (mDefaultPartialContentConstructors.findValue(&default_key)); if (constructor) { constructor->generateDefaultContent(this, resourceId, eventTypeKey, eventType); } // Is there a callback for this eventType? (Probably so.) UtlString eventTypeString(eventType); PublishCallbackContainer* callbackContainer = dynamic_cast <PublishCallbackContainer*> (mEventContentCallbacks.find(&eventTypeString)); if (callbackContainer) { // See if resource-specific (full) content exists now. PublishContentContainer* newContent = dynamic_cast <PublishContentContainer*> (mContentEntries.find(&key)); // If no (full) content was generated, check if (fixed) default content exists. PublishContentContainer* defaultContent = NULL; if (!newContent) { defaultContent = dynamic_cast <PublishContentContainer*> (mDefaultContentEntries.find(&default_key)); } // Now, newContent is non-NULL if default content exists for // 'key', which means that the resource still has // publishable content. if (newContent || defaultContent) { // Replace the new content for the resource with the previous content. if (newContent) { mContentEntries.removeReference(newContent); } PublishContentContainer* newPartialContent = dynamic_cast <PublishContentContainer*> (mPartialContentEntries.remove(&key)); // Insert the previous content for the resource. if (content) { mContentEntries.insert(content); } if (partialContent) { mPartialContentEntries.insert(partialContent); } // Do a "publish" callback. (callbackContainer->mpCallback)(callbackContainer->mpApplicationData, resourceId, eventTypeKey, eventTypeString, NULL); // Remove the previous content again. // Insert the previous content for the resource. if (content) { mContentEntries.removeReference(content); } if (partialContent) { mPartialContentEntries.removeReference(partialContent); } // Insert the new content again. if (newContent) { mContentEntries.insert(newContent); } if (newPartialContent) { mContentEntries.insert(newPartialContent); } } else { // No publishable content, so do an "unpublish" callback. (callbackContainer->mpCallback)(callbackContainer->mpApplicationData, resourceId, eventTypeKey, eventTypeString, reason); } } // Delete the old content containers. if (content) { delete content; } if (partialContent) { delete partialContent; } } else { // Remove default content. mDefaultContentEntries.destroy(&key); // Remove any default constructor. mDefaultContentConstructors.destroy(&key); } unlock(); }
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; }
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); }