From 6fb2c1b578d6f24570624396de0e0815aabdf7a5 Mon Sep 17 00:00:00 2001 From: fgerlits Date: Tue, 16 Nov 2004 15:21:16 +0000 Subject: [PATCH] added (so far mostly empty) WebStorageClient --- livesupport/modules/storage/etc/Makefile.in | 8 +- .../modules/storage/etc/webStorage.xml | 45 ++ .../modules/storage/src/TestStorageClient.cxx | 4 +- .../modules/storage/src/TestStorageClient.h | 12 +- .../modules/storage/src/WebStorageClient.cxx | 600 ++++++++++++++++++ .../modules/storage/src/WebStorageClient.h | 331 ++++++++++ .../storage/src/WebStorageClientTest.cxx | 304 +++++++++ .../storage/src/WebStorageClientTest.h | 167 +++++ 8 files changed, 1463 insertions(+), 8 deletions(-) create mode 100644 livesupport/modules/storage/etc/webStorage.xml create mode 100644 livesupport/modules/storage/src/WebStorageClient.cxx create mode 100644 livesupport/modules/storage/src/WebStorageClient.h create mode 100644 livesupport/modules/storage/src/WebStorageClientTest.cxx create mode 100644 livesupport/modules/storage/src/WebStorageClientTest.h diff --git a/livesupport/modules/storage/etc/Makefile.in b/livesupport/modules/storage/etc/Makefile.in index 968214ebe..0fdc29db2 100644 --- a/livesupport/modules/storage/etc/Makefile.in +++ b/livesupport/modules/storage/etc/Makefile.in @@ -21,7 +21,7 @@ # # # Author : $Author: fgerlits $ -# Version : $Revision: 1.5 $ +# Version : $Revision: 1.6 $ # Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/etc/Makefile.in,v $ # # @configure_input@ @@ -94,10 +94,14 @@ LDFLAGS = @LDFLAGS@ -L${USR_LIB_DIR} -L${CORE_LIB_DIR} -L${LIB_DIR} # Dependencies #------------------------------------------------------------------------------- STORAGE_LIB_OBJS = ${TMP_DIR}/StorageClientFactory.o \ - ${TMP_DIR}/TestStorageClient.o + ${TMP_DIR}/TestStorageClient.o \ + ${TMP_DIR}/WebStorageClient.o + TEST_RUNNER_OBJS = ${TMP_DIR}/TestStorageClientTest.o \ ${TMP_DIR}/StorageServerLoginTest.o \ + ${TMP_DIR}/WebStorageClientTest.o \ ${TMP_DIR}/TestRunner.o + TEST_RUNNER_LIBS = -l${STORAGE_LIB} -l${CORE_LIB} -lxml++-1.0 -lcppunit -ldl \ -lxmlrpc++ -lssl diff --git a/livesupport/modules/storage/etc/webStorage.xml b/livesupport/modules/storage/etc/webStorage.xml new file mode 100644 index 000000000..b68847c5e --- /dev/null +++ b/livesupport/modules/storage/etc/webStorage.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + diff --git a/livesupport/modules/storage/src/TestStorageClient.cxx b/livesupport/modules/storage/src/TestStorageClient.cxx index 165a31010..2167b4264 100644 --- a/livesupport/modules/storage/src/TestStorageClient.cxx +++ b/livesupport/modules/storage/src/TestStorageClient.cxx @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.15 $ + Version : $Revision: 1.16 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.cxx,v $ ------------------------------------------------------------------------------*/ @@ -60,7 +60,7 @@ using namespace LiveSupport::Storage; const std::string TestStorageClient::configElementNameStr = "testStorage"; /*------------------------------------------------------------------------------ - * The name of the config element for this class + * The name of the config element attribute for the temp files *----------------------------------------------------------------------------*/ static const std::string localTempStorageAttrName = "tempFiles"; diff --git a/livesupport/modules/storage/src/TestStorageClient.h b/livesupport/modules/storage/src/TestStorageClient.h index 17faca630..325deefec 100644 --- a/livesupport/modules/storage/src/TestStorageClient.h +++ b/livesupport/modules/storage/src/TestStorageClient.h @@ -22,7 +22,7 @@ Author : $Author: fgerlits $ - Version : $Revision: 1.13 $ + Version : $Revision: 1.14 $ Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/TestStorageClient.h,v $ ------------------------------------------------------------------------------*/ @@ -67,7 +67,7 @@ using namespace LiveSupport::Core; * A dummy storage client, only used for test purposes. * * @author $Author: fgerlits $ - * @version $Revision: 1.13 $ + * @version $Revision: 1.14 $ */ class TestStorageClient : virtual public Configurable, @@ -168,8 +168,10 @@ class TestStorageClient : /** * Acquire the resources for the playlist. * - * Produces absolute paths prefixed by "file://"; e.g., - * "file:///some/dir/test1.mp3" and "file:///tmp/tempfileXXXX.smil". + * The Playlist returned has a uri field (read using getUri()) + * which points to a playable SMIL file. This URI is a random string + * appended to the temp storage path read from the configuration file, + * plus a ".smil" extension. * * @param id the id of the playlist to acquire. * @return a new Playlist instance containing a uri field which @@ -247,6 +249,8 @@ class TestStorageClient : /** * Acquire the resources for the audio clip with the specified id. * + * Returns an AudioClip instance with a valid uri field, which points + * to the binary sound file. * Assumes URIs in the config file are relative paths prefixed by * "file:"; e.g., "file:var/test1.mp3". * diff --git a/livesupport/modules/storage/src/WebStorageClient.cxx b/livesupport/modules/storage/src/WebStorageClient.cxx new file mode 100644 index 000000000..865c62690 --- /dev/null +++ b/livesupport/modules/storage/src/WebStorageClient.cxx @@ -0,0 +1,600 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: fgerlits $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.cxx,v $ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#if HAVE_UNISTD_H +#include +#else +#error "Need unistd.h" +#endif + +#include +#include + +#include "WebStorageClient.h" + +using namespace boost::posix_time; + +using namespace LiveSupport::Core; +using namespace LiveSupport::Storage; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +/*------------------------------------------------------------------------------ + * The name of the config element for this class + *----------------------------------------------------------------------------*/ +const std::string WebStorageClient::configElementNameStr = "webStorage"; + +/*------------------------------------------------------------------------------ + * The name of the config element attribute for the temp files + *----------------------------------------------------------------------------*/ +static const std::string localTempStorageAttrName = "tempFiles"; + +/*------------------------------------------------------------------------------ + * The name of the config child element for the storage server location + *----------------------------------------------------------------------------*/ +static const std::string locationConfigElementName = "location"; + +/*------------------------------------------------------------------------------ + * The name of the config element attribute for the storage server name + *----------------------------------------------------------------------------*/ +static const std::string locationServerAttrName = "server"; + +/*------------------------------------------------------------------------------ + * The name of the config element attribute for the storage server port + *----------------------------------------------------------------------------*/ +static const std::string locationPortAttrName = "port"; + +/*------------------------------------------------------------------------------ + * The name of the config child element for the storage server login + *----------------------------------------------------------------------------*/ +static const std::string identityConfigElementName = "identity"; + +/*------------------------------------------------------------------------------ + * The name of the config child element for the storage server login name + *----------------------------------------------------------------------------*/ +static const std::string identityLoginNameAttrName = "login"; + +/*------------------------------------------------------------------------------ + * The name of the config child element for the storage server login password + *----------------------------------------------------------------------------*/ +static const std::string identityPasswordAttrName = "pass"; + +/*------------------------------------------------------------------------------ + * The XML version used to create the SMIL file. + *----------------------------------------------------------------------------*/ +static const std::string xmlVersion = "1.0"; + +/*------------------------------------------------------------------------------ + * The name of the SMIL root node. + *----------------------------------------------------------------------------*/ +static const std::string smilRootNodeName = "smil"; + +/*------------------------------------------------------------------------------ + * The name of the SMIL language description attribute. + *----------------------------------------------------------------------------*/ +static const std::string smilLanguageAttrName = "xmlns"; + +/*------------------------------------------------------------------------------ + * The value of the SMIL language description attribute. + *----------------------------------------------------------------------------*/ +static const std::string smilLanguageAttrValue + = "http://www.w3.org/2001/SMIL20/Language"; + +/*------------------------------------------------------------------------------ + * The name of the SMIL real networks extension attribute. + *----------------------------------------------------------------------------*/ +static const std::string smilExtensionsAttrName = "xmlns:rn"; + +/*------------------------------------------------------------------------------ + * The value of the SMIL real networks extension attribute. + *----------------------------------------------------------------------------*/ +static const std::string smilExtensionsAttrValue + = "http://features.real.com/2001/SMIL20/Extensions"; + +/*------------------------------------------------------------------------------ + * The name of the body node in the SMIL file. + *----------------------------------------------------------------------------*/ +static const std::string smilBodyNodeName = "body"; + +/*------------------------------------------------------------------------------ + * The name of the sequential audio clip list node in the SMIL file. + *----------------------------------------------------------------------------*/ +static const std::string smilSeqNodeName = "seq"; + +/*------------------------------------------------------------------------------ + * The name of the audio clip element node in the SMIL file. + *----------------------------------------------------------------------------*/ +static const std::string smilAudioClipNodeName = "audio"; + +/*------------------------------------------------------------------------------ + * The name of the attribute containing the URI of the audio clip element. + *----------------------------------------------------------------------------*/ +static const std::string smilAudioClipUriAttrName = "src"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Configure the web storage client. + *----------------------------------------------------------------------------*/ +void +WebStorageClient :: configure(const xmlpp::Element & element) + throw (std::invalid_argument, + std::logic_error) +{ + if (element.get_name() != configElementNameStr) { + std::string eMsg = "Bad configuration element "; + eMsg += element.get_name(); + throw std::invalid_argument(eMsg); + } + + const xmlpp::Attribute * attribute; + + if (!(attribute = element.get_attribute(localTempStorageAttrName))) { + std::string eMsg = "Missing attribute "; + eMsg += localTempStorageAttrName; + throw std::invalid_argument(eMsg); + } + + localTempStorage = attribute->get_value(); + + // read the storage server location + xmlpp::Node::NodeList childNodes + = element.get_children(locationConfigElementName); + xmlpp::Node::NodeList::iterator it = childNodes.begin(); + + if (it == childNodes.end()) { + std::string eMsg = "missing "; + eMsg += locationConfigElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + + const xmlpp::Element * locationConfigElement + = dynamic_cast (*it); + if (!(attribute = locationConfigElement + ->get_attribute(locationServerAttrName))) { + std::string eMsg = "Missing attribute "; + eMsg += locationServerAttrName; + throw std::invalid_argument(eMsg); + } + storageServerName = attribute->get_value(); + + if (!(attribute = locationConfigElement + ->get_attribute(locationPortAttrName))) { + std::string eMsg = "Missing attribute "; + eMsg += locationPortAttrName; + throw std::invalid_argument(eMsg); + } + std::stringstream storageServerPortValue(attribute->get_value()); + storageServerPortValue >> storageServerPort; + + ++it; + if (it != childNodes.end()) { + std::string eMsg = "more than one "; + eMsg += locationConfigElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + + // read the login and password to the storage server + childNodes = element.get_children(identityConfigElementName); + it = childNodes.begin(); + + if (it == childNodes.end()) { + std::string eMsg = "missing "; + eMsg += identityConfigElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + + const xmlpp::Element * identityConfigElement + = dynamic_cast (*it); + if (!(attribute = identityConfigElement + ->get_attribute(identityLoginNameAttrName))) { + std::string eMsg = "Missing attribute "; + eMsg += identityLoginNameAttrName; + throw std::invalid_argument(eMsg); + } + loginName = attribute->get_value(); + + if (!(attribute = identityConfigElement + ->get_attribute(identityPasswordAttrName))) { + std::string eMsg = "Missing attribute "; + eMsg += identityPasswordAttrName; + throw std::invalid_argument(eMsg); + } + password = attribute->get_value(); + + ++it; + if (it != childNodes.end()) { + std::string eMsg = "more than one "; + eMsg += identityConfigElementName; + eMsg += " XML element"; + throw std::invalid_argument(eMsg); + } + + // iterate through the playlist elements ... + childNodes = element.get_children(Playlist::getConfigElementName()); + it = childNodes.begin(); + playlistMap.clear(); + + while (it != childNodes.end()) { + Ptr::Ref playlist(new Playlist); + const xmlpp::Element * element = + dynamic_cast (*it); + playlist->configure(*element); + playlistMap[playlist->getId()->getId()] = playlist; + ++it; + } + + // ... and the the audio clip elements + childNodes = element.get_children(AudioClip::getConfigElementName()); + it = childNodes.begin(); + audioClipMap.clear(); + + while (it != childNodes.end()) { + Ptr::Ref audioClip(new AudioClip); + const xmlpp::Element * element = + dynamic_cast (*it); + audioClip->configure(*element); + audioClipMap[audioClip->getId()->getId()] = audioClip; + ++it; + } +} + + +/*------------------------------------------------------------------------------ + * Tell if a playlist exists. + *----------------------------------------------------------------------------*/ +const bool +WebStorageClient :: existsPlaylist(Ptr::Ref id) const + throw () +{ + return playlistMap.count(id->getId()) == 1 ? true : false; +} + + +/*------------------------------------------------------------------------------ + * Return a playlist. + *----------------------------------------------------------------------------*/ +Ptr::Ref +WebStorageClient :: getPlaylist(Ptr::Ref id) const + throw (std::invalid_argument) +{ + PlaylistMap::const_iterator it = playlistMap.find(id->getId()); + + if (it == playlistMap.end()) { + throw std::invalid_argument("no such playlist"); + } + + return it->second; +} + + +/*------------------------------------------------------------------------------ + * Acquire resources for a playlist. + *----------------------------------------------------------------------------*/ +Ptr::Ref +WebStorageClient :: acquirePlaylist(Ptr::Ref id) const + throw (std::logic_error) +{ + PlaylistMap::const_iterator playlistMapIt = playlistMap.find(id->getId()); + + if (playlistMapIt == playlistMap.end()) { + throw std::invalid_argument("no such playlist"); + } + + Ptr::Ref oldPlaylist = playlistMapIt->second; + Ptr::Ref playlength(new time_duration( + *(oldPlaylist->getPlaylength()) )); + Ptr::Ref newPlaylist(new Playlist(UniqueId::generateId(), + playlength)); + Ptr::Ref + smilDocument(new xmlpp::Document(xmlVersion)); + xmlpp::Element * smilRootNode + = smilDocument->create_root_node(smilRootNodeName); + smilRootNode->set_attribute(smilLanguageAttrName, + smilLanguageAttrValue); + smilRootNode->set_attribute(smilExtensionsAttrName, + smilExtensionsAttrValue); + + xmlpp::Element * smilBodyNode + = smilRootNode->add_child(smilBodyNodeName); + xmlpp::Element * smilSeqNode + = smilBodyNode->add_child(smilSeqNodeName); + + Playlist::const_iterator it = oldPlaylist->begin(); + + while (it != oldPlaylist->end()) { + Ptr::Ref audioClip = acquireAudioClip( it->second + ->getAudioClip() + ->getId() ); + Ptr::Ref relativeOffset(new time_duration( + *(it->second->getRelativeOffset()) )); + Ptr::Ref oldFadeInfo = it->second->getFadeInfo(); + Ptr::Ref newFadeInfo; + if (oldFadeInfo) { // careful: fadeInfo may be 0 + newFadeInfo.reset(new FadeInfo(*oldFadeInfo)); + } + + newPlaylist->addAudioClip(audioClip, + relativeOffset, + newFadeInfo); + + xmlpp::Element * smilAudioClipNode + = smilSeqNode->add_child(smilAudioClipNodeName); + smilAudioClipNode->set_attribute( + smilAudioClipUriAttrName, + *(audioClip->getUri()) ); + ++it; + } + + std::stringstream fileName; + fileName << localTempStorage << newPlaylist->getId()->getId() + << "#" << std::rand() << ".smil"; + + smilDocument->write_to_file(fileName.str(), "UTF-8"); + + Ptr::Ref playlistUri(new std::string(fileName.str())); + newPlaylist->setUri(playlistUri); + return newPlaylist; +} + + +/*------------------------------------------------------------------------------ + * Release a playlist. + *----------------------------------------------------------------------------*/ +void +WebStorageClient :: releasePlaylist(Ptr::Ref playlist) const + throw (std::logic_error) +{ + if (! playlist->getUri()) { + throw std::logic_error("playlist URI not found"); + } + + std::ifstream ifs(playlist->getUri()->substr(7).c_str()); + if (!ifs) { + ifs.close(); + throw std::logic_error("playlist temp file not found"); + } + ifs.close(); + + std::remove(playlist->getUri()->substr(7).c_str()); + + int badAudioClips = 0; + Playlist::const_iterator it = playlist->begin(); + while (it != playlist->end()) { + try { + releaseAudioClip(it->second->getAudioClip()); + } + catch (std::invalid_argument &e) { + ++badAudioClips; + } + ++it; + } + + Ptr::Ref nullPointer; + playlist->setUri(nullPointer); + + if (badAudioClips) { + std::stringstream eMsg; + eMsg << "could not release " << badAudioClips + << " audio clips in playlist"; + throw std::logic_error(eMsg.str()); + } +} + + +/*------------------------------------------------------------------------------ + * Delete a playlist. + *----------------------------------------------------------------------------*/ +void +WebStorageClient :: deletePlaylist(Ptr::Ref id) + throw (std::invalid_argument) +{ + // erase() returns the number of entries found & erased + if (!playlistMap.erase(id->getId())) { + throw std::invalid_argument("no such playlist"); + } +} + + +/*------------------------------------------------------------------------------ + * Return a listing of all the playlists in the playlist store. + *----------------------------------------------------------------------------*/ +Ptr::Ref> >::Ref +WebStorageClient :: getAllPlaylists(void) const + throw () +{ + PlaylistMap::const_iterator it = playlistMap.begin(); + Ptr::Ref> >::Ref + playlistVector (new std::vector::Ref>); + + while (it != playlistMap.end()) { + playlistVector->push_back(it->second); + ++it; + } + + return playlistVector; +} + + +/*------------------------------------------------------------------------------ + * Create a new playlist. + *----------------------------------------------------------------------------*/ +Ptr::Ref +WebStorageClient :: createPlaylist() throw () +{ + // generate a new UniqueId -- TODO: fix UniqueId to make sure + // this is really unique; not checked here! + Ptr::Ref playlistId = + Ptr::Ref(UniqueId :: generateId()); + + Ptr::Ref playLength = + Ptr::Ref(new time_duration(0,0,0)); + + Ptr::Ref playlist = + Ptr::Ref(new Playlist(playlistId, playLength)); + + playlistMap[playlistId->getId()] = playlist; + + return playlist; +} + + +/*------------------------------------------------------------------------------ + * Tell if an audio clip exists. + *----------------------------------------------------------------------------*/ +const bool +WebStorageClient :: existsAudioClip(Ptr::Ref id) const + throw () +{ + return audioClipMap.count(id->getId()) == 1 ? true : false; +} + + +/*------------------------------------------------------------------------------ + * Return an audio clip. + *----------------------------------------------------------------------------*/ +Ptr::Ref +WebStorageClient :: getAudioClip(Ptr::Ref id) const + throw (std::invalid_argument) +{ + AudioClipMap::const_iterator it = audioClipMap.find(id->getId()); + + if (it == audioClipMap.end()) { + throw std::invalid_argument("no such audio clip"); + } + + return it->second; +} + + +/*------------------------------------------------------------------------------ + * Acquire resources for an audio clip. + *----------------------------------------------------------------------------*/ +Ptr::Ref +WebStorageClient :: acquireAudioClip(Ptr::Ref id) const + throw (std::logic_error) +{ + AudioClipMap::const_iterator it = audioClipMap.find(id->getId()); + + if (it == audioClipMap.end()) { + throw std::invalid_argument("no such audio clip"); + } + + Ptr::Ref storedAudioClip = it->second; + + if (! storedAudioClip->getUri()) { + throw std::logic_error("audio clip URI not found"); + } + // cut the "file:" off + std::string audioClipFileName = storedAudioClip->getUri()->substr(5); + + std::ifstream ifs(audioClipFileName.c_str()); + if (!ifs) { + ifs.close(); + throw std::logic_error("could not read audio clip"); + } + ifs.close(); + + Ptr::Ref audioClip(new AudioClip(*storedAudioClip)); + + Ptr::Ref audioClipUri(new std::string("file://")); + *audioClipUri += get_current_dir_name(); // doesn't work if current + *audioClipUri += "/"; // dir = /, but OK for now + *audioClipUri += audioClipFileName; + + audioClip->setUri(audioClipUri); + return audioClip; +} + + +/*------------------------------------------------------------------------------ + * Release an audio clip. + *----------------------------------------------------------------------------*/ +void +WebStorageClient :: releaseAudioClip(Ptr::Ref audioClip) const + throw (std::logic_error) +{ + if (*(audioClip->getUri()) == "") { + throw std::logic_error("audio clip URI not found"); + } + + Ptr::Ref nullPointer; + audioClip->setUri(nullPointer); +} + + +/*------------------------------------------------------------------------------ + * Delete an audio clip. + *----------------------------------------------------------------------------*/ +void +WebStorageClient :: deleteAudioClip(Ptr::Ref id) + throw (std::invalid_argument) +{ + // erase() returns the number of entries found & erased + if (!audioClipMap.erase(id->getId())) { + throw std::invalid_argument("no such audio clip"); + } +} + + +/*------------------------------------------------------------------------------ + * Return a listing of all the audio clips in the audio clip store. + *----------------------------------------------------------------------------*/ +Ptr::Ref> >::Ref +WebStorageClient :: getAllAudioClips(void) const + throw () +{ + AudioClipMap::const_iterator it = audioClipMap.begin(); + Ptr::Ref> >::Ref + audioClipVector (new std::vector::Ref>); + + while (it != audioClipMap.end()) { + audioClipVector->push_back(it->second); + ++it; + } + + return audioClipVector; +} + diff --git a/livesupport/modules/storage/src/WebStorageClient.h b/livesupport/modules/storage/src/WebStorageClient.h new file mode 100644 index 000000000..ce0edd04b --- /dev/null +++ b/livesupport/modules/storage/src/WebStorageClient.h @@ -0,0 +1,331 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: fgerlits $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClient.h,v $ + +------------------------------------------------------------------------------*/ +#ifndef WebStorageClient_h +#define WebStorageClient_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include + +#include "LiveSupport/Core/Ptr.h" +#include "LiveSupport/Core/UniqueId.h" +#include "LiveSupport/Core/Playlist.h" +#include "LiveSupport/Core/Configurable.h" +#include "LiveSupport/Core/StorageClientInterface.h" + + +namespace LiveSupport { +namespace Storage { + +using namespace LiveSupport; +using namespace LiveSupport::Core; + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * An interface to the (possibly remote) php storage server. + * + * @author $Author: fgerlits $ + * @version $Revision: 1.1 $ + */ +class WebStorageClient : + virtual public Configurable, + virtual public StorageClientInterface +{ + private: + /** + * The name of the configuration XML elmenent used by WebStorageClient + */ + static const std::string configElementNameStr; + + /** + * The map type containing the playlists by their ids. + */ + typedef std::map::Ref> + PlaylistMap; + + /** + * The map holding all contained playlists, by ids. + */ + PlaylistMap playlistMap; + + /** + * The map type containing the audio clips by their ids. + */ + typedef std::map::Ref> + AudioClipMap; + + /** + * The map holding all contained audio clips, by ids. + */ + AudioClipMap audioClipMap; + + /** + * The path where the temporary SMIL files are strored. + */ + std::string localTempStorage; + + /** + * The name of the storage server, e.g. "myserver.mycompany.com". + */ + std::string storageServerName; + + /** + * The port wher the storage server is listening (default is 80). + */ + int storageServerPort; + + /** + * The login name to the storage server. + */ + std::string loginName; + + /** + * The password to the storage server. + */ + std::string password; + + + public: + /** + * A virtual destructor, as this class has virtual functions. + */ + virtual + ~WebStorageClient(void) throw () + { + } + + /** + * Return the name of the XML element this object expects + * to be sent to a call to configure(). + * + * @return the name of the expected XML configuration element. + */ + static const std::string + getConfigElementName(void) throw () + { + return configElementNameStr; + } + + /** + * Configure the object based on the XML element supplied. + * + * @param element the XML element to configure the object from. + * @exception std::invalid_argument if the supplied XML element + * contains bad configuraiton information + * @exception std::logic_error if the scheduler daemon has already + * been configured, and can not be reconfigured. + */ + virtual void + configure(const xmlpp::Element & element) + throw (std::invalid_argument, + std::logic_error); + + /** + * Tell if a playlist with a given id exists. + * + * @param id the id of the playlist to check for. + * @return true if a playlist with the specified id exists, + * false otherwise. + */ + virtual const bool + existsPlaylist(Ptr::Ref id) const + throw (); + + /** + * Return a playlist with the specified id. + * + * @param id the id of the playlist to return. + * @return the requested playlist. + * @exception std::invalid_argument if no playlist with the specified + * id exists. + */ + virtual Ptr::Ref + getPlaylist(Ptr::Ref id) const + throw (std::invalid_argument); + + /** + * Acquire the resources for the playlist. + * + * The Playlist returned has a uri field (read using getUri()) + * which points to a playable SMIL file. This URI is a random string + * appended to the temp storage path read from the configuration file, + * plus a ".smil" extension. + * + * @param id the id of the playlist to acquire. + * @return a new Playlist instance containing a uri field which + * points to an executable (playable) SMIL representation of + * the playlist (in the local storage). + * @exception std::invalid_argument if no playlist with the specified + * specified id exists. + */ + virtual Ptr::Ref + acquirePlaylist(Ptr::Ref id) const + throw (std::logic_error); + + /** + * Release the resources (audio clips, other playlists) used + * in a playlist. The uri of the playlist is no longer valid, and + * the uri field is deleted. + * + * @param playlist the playlist to release. + * @exception std::logic_error if the playlist has no uri field, + * or the file does not exist, etc. + */ + virtual void + releasePlaylist(Ptr::Ref playlist) const + throw (std::logic_error); + + /** + * Delete the playlist with the specified id. + * + * @param id the id of the playlist to be deleted. + * @exception std::invalid_argument if no playlist with the specified + * id exists. + */ + virtual void + deletePlaylist(Ptr::Ref id) + throw (std::invalid_argument); + + /** + * Return a list of all playlists in the playlist store. + * + * @return a vector containing the playlists. + */ + virtual Ptr::Ref> >::Ref + getAllPlaylists(void) const throw (); + + /** + * Create a new playlist. + * + * @return the newly created playlist. + */ + virtual Ptr::Ref + createPlaylist() throw (); + + /** + * Tell if an audio clip with a given id exists. + * + * @param id the id of the audio clip to check for. + * @return true if an audio clip with the specified id exists, + * false otherwise. + */ + virtual const bool + existsAudioClip(Ptr::Ref id) const + throw (); + + /** + * Return an audio clip with the specified id. + * + * @param id the id of the audio clip to return. + * @return the requested audio clip. + * @exception std::invalid_argument if no audio clip with the + * specified id exists. + */ + virtual Ptr::Ref + getAudioClip(Ptr::Ref id) const + throw (std::invalid_argument); + + /** + * Acquire the resources for the audio clip with the specified id. + * + * Returns an AudioClip instance with a valid uri field, which points + * to the binary sound file. + * + * @param id the id of the audio clip to acquire. + * @return a new AudioClip instance, containing a uri field which + * points to (a way of getting) the sound file. + * @exception std::invalid_argument if no audio clip with the + * specified id exists. + */ + virtual Ptr::Ref + acquireAudioClip(Ptr::Ref id) const + throw (std::logic_error); + + /** + * Release the resource (sound file) used by an audio clip. The + * uri of the audio clip is no longer valid, and the uri field is + * deleted. + * + * @param id the id of the audio clip to release. + * @exception std::logic_error if the audio clip has no uri field, + * or the file does not exist, etc. + */ + virtual void + releaseAudioClip(Ptr::Ref audioClip) const + throw (std::logic_error); + + /** + * Delete the audio clip with the specified id. + * + * @param id the id of the audio clip to be deleted. + * @exception std::invalid_argument if no audio clip with the + * specified id exists. + */ + virtual void + deleteAudioClip(Ptr::Ref id) + throw (std::invalid_argument); + + /** + * Return a list of all audio clips in the playlist store. + * + * @return a vector containing the audio clips. + */ + virtual Ptr::Ref> >::Ref + getAllAudioClips(void) const throw (); + +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Core +} // namespace LiveSupport + +#endif // WebStorageClient_h + diff --git a/livesupport/modules/storage/src/WebStorageClientTest.cxx b/livesupport/modules/storage/src/WebStorageClientTest.cxx new file mode 100644 index 000000000..4dba2a8db --- /dev/null +++ b/livesupport/modules/storage/src/WebStorageClientTest.cxx @@ -0,0 +1,304 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: fgerlits $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClientTest.cxx,v $ + +------------------------------------------------------------------------------*/ + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#if HAVE_UNISTD_H +#include +#else +#error "Need unistd.h" +#endif + + +#include +#include +#include + +#include "WebStorageClient.h" +#include "WebStorageClientTest.h" + + +using namespace std; +using namespace LiveSupport::Core; +using namespace LiveSupport::Storage; + +/* =================================================== local data structures */ + + +/* ================================================ local constants & macros */ + +CPPUNIT_TEST_SUITE_REGISTRATION(WebStorageClientTest); + +/** + * The name of the configuration file for the storage client factory daemon. + */ +static const std::string configFileName = "etc/webStorage.xml"; + + +/* =============================================== local function prototypes */ + + +/* ============================================================= module code */ + +/*------------------------------------------------------------------------------ + * Set up the test environment + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: setUp(void) throw () +{ + try { + Ptr::Ref parser( + new xmlpp::DomParser(configFileName, true)); + const xmlpp::Document * document = parser->get_document(); + const xmlpp::Element * root = document->get_root_node(); + + wsc.reset(new WebStorageClient()); + wsc->configure(*root); + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL("semantic error in configuration file"); + } catch (xmlpp::exception &e) { + CPPUNIT_FAIL("error parsing configuration file"); + } +} + + +/*------------------------------------------------------------------------------ + * Clean up the test environment + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: tearDown(void) throw () +{ + wsc.reset(); +} + + +/*------------------------------------------------------------------------------ + * Test to see if the singleton Hello object is accessible + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: firstTest(void) + throw (CPPUNIT_NS::Exception) +{/* + Ptr::Ref id1(new UniqueId(1)); + Ptr::Ref id2(new UniqueId(77)); + + CPPUNIT_ASSERT(wsc->existsPlaylist(id1)); + CPPUNIT_ASSERT(!wsc->existsPlaylist(id2)); + + Ptr::Ref playlist = wsc->getPlaylist(id1); + CPPUNIT_ASSERT(playlist->getId()->getId() == id1->getId()); +*/} + + +/*------------------------------------------------------------------------------ + * Testing the deletePlaylist method + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: deletePlaylistTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref id1(new UniqueId(1)); + Ptr::Ref id2(new UniqueId(77)); + + try { + wsc->deletePlaylist(id2); + CPPUNIT_FAIL("allowed to delete non-existent playlist"); + } catch (std::invalid_argument &e) { + } + try { + wsc->deletePlaylist(id1); + } catch (std::invalid_argument &e) { + CPPUNIT_FAIL("cannot delete existing playlist"); + } + try { + wsc->deletePlaylist(id1); + CPPUNIT_FAIL("allowed to delete non-existent playlist"); + } catch (std::invalid_argument &e) { + } +} + + +/*------------------------------------------------------------------------------ + * Testing the getAllPlaylists method + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: getAllPlaylistsTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref> >::Ref playlistVector = + wsc->getAllPlaylists(); + CPPUNIT_ASSERT(playlistVector->size() == 1); + + Ptr::Ref playlist = (*playlistVector)[0]; + CPPUNIT_ASSERT((int) (playlist->getId()->getId()) == 1); +} + + +/*------------------------------------------------------------------------------ + * Testing the createPlaylist method + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: createPlaylistTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref playlist = wsc->createPlaylist(); + + CPPUNIT_ASSERT(wsc->existsPlaylist(playlist->getId())); +} + + +/*------------------------------------------------------------------------------ + * Testing the audio clip operations + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: audioClipTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref id2(new UniqueId(10002)); + Ptr::Ref id77(new UniqueId(10077)); + + CPPUNIT_ASSERT(wsc->existsAudioClip(id2)); + CPPUNIT_ASSERT(!wsc->existsAudioClip(id77)); + + Ptr::Ref audioClip = wsc->getAudioClip(id2); + CPPUNIT_ASSERT(audioClip->getId()->getId() == id2->getId()); + CPPUNIT_ASSERT(audioClip->getPlaylength()->total_seconds() + == 30*60); + + Ptr::Ref> >::Ref audioClipVector = + wsc->getAllAudioClips(); + CPPUNIT_ASSERT(audioClipVector->size() == 2); + + audioClip = (*audioClipVector)[0]; + CPPUNIT_ASSERT((int) (audioClip->getId()->getId()) == 10001); + + wsc->deleteAudioClip(id2); + CPPUNIT_ASSERT(!wsc->existsAudioClip(id2)); +} + + +/*------------------------------------------------------------------------------ + * Testing the acquire / release operations + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: acquireAudioClipTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref id2(new UniqueId(10002)); + Ptr::Ref id77(new UniqueId(10077)); + Ptr::Ref audioClip; + + try { + audioClip = wsc->acquireAudioClip(id2); + } + catch (std::logic_error &e) { + std::string eMsg = "could not acquire audio clip:\n"; + eMsg += e.what(); + CPPUNIT_FAIL(eMsg); + } + string audioClipUri("file://"); + audioClipUri += get_current_dir_name(); + audioClipUri += "/var/test2.mp3"; + CPPUNIT_ASSERT(*(audioClip->getUri()) == audioClipUri); + + try { + wsc->releaseAudioClip(audioClip); + } + catch (std::logic_error &e) { + std::string eMsg = "could not release audio clip:\n"; + eMsg += e.what(); + CPPUNIT_FAIL(eMsg); + } + + try { + audioClip = wsc->acquireAudioClip(id77); + CPPUNIT_FAIL("allowed to acquire non-existent audio clip"); + } + catch (std::logic_error &e) { + } +} + + +/*------------------------------------------------------------------------------ + * Testing the acquire / release operations + *----------------------------------------------------------------------------*/ +void +WebStorageClientTest :: acquirePlaylistTest(void) + throw (CPPUNIT_NS::Exception) +{ + Ptr::Ref id1(new UniqueId(1)); + Ptr::Ref id77(new UniqueId(77)); + Ptr::Ref playlist; + + try { + playlist = wsc->acquirePlaylist(id1); + } + catch (std::logic_error &e) { + std::string eMsg = "could not acquire playlist:\n"; + eMsg += e.what(); + CPPUNIT_FAIL(eMsg); + } + CPPUNIT_ASSERT(playlist->getUri()); + CPPUNIT_ASSERT(playlist->getUri()->substr(0,7) == "file://"); + + std::ifstream ifs1(playlist->getUri()->substr(7).c_str()); + if (!ifs1) { + ifs1.close(); + CPPUNIT_FAIL("temp file not created correctly"); + } + ifs1.close(); + + string savedTempFilePath = playlist->getUri()->substr(7); + try { + wsc->releasePlaylist(playlist); + } + catch (std::logic_error &e) { + std::string eMsg = "could not release playlist:\n"; + eMsg += e.what(); + CPPUNIT_FAIL(eMsg); + } + CPPUNIT_ASSERT(!playlist->getUri()); + std::ifstream ifs2(savedTempFilePath.c_str()); + if (ifs2) { + ifs2.close(); + CPPUNIT_FAIL("temp file not destroyed correctly"); + } + ifs2.close(); + + try { + playlist = wsc->acquirePlaylist(id77); + CPPUNIT_FAIL("allowed to acquire non-existent playlist"); + } + catch (std::logic_error &e) { + } +} diff --git a/livesupport/modules/storage/src/WebStorageClientTest.h b/livesupport/modules/storage/src/WebStorageClientTest.h new file mode 100644 index 000000000..d74ab2a3f --- /dev/null +++ b/livesupport/modules/storage/src/WebStorageClientTest.h @@ -0,0 +1,167 @@ +/*------------------------------------------------------------------------------ + + Copyright (c) 2004 Media Development Loan Fund + + This file is part of the LiveSupport project. + http://livesupport.campware.org/ + To report bugs, send an e-mail to bugs@campware.org + + LiveSupport is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + LiveSupport is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LiveSupport; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + + Author : $Author: fgerlits $ + Version : $Revision: 1.1 $ + Location : $Source: /home/paul/cvs2svn-livesupport/newcvsrepo/livesupport/modules/storage/src/WebStorageClientTest.h,v $ + +------------------------------------------------------------------------------*/ +#ifndef WebStorageClientTest_h +#define WebStorageClientTest_h + +#ifndef __cplusplus +#error This is a C++ include file +#endif + + +/* ============================================================ include files */ + +#ifdef HAVE_CONFIG_H +#include "configure.h" +#endif + +#include + + +namespace LiveSupport { +namespace Storage { + +/* ================================================================ constants */ + + +/* =================================================================== macros */ + + +/* =============================================================== data types */ + +/** + * Unit test for the UploadPlaylistMetohd class. + * + * @author $Author: fgerlits $ + * @version $Revision: 1.1 $ + * @see WebStorageClient + */ +class WebStorageClientTest : public CPPUNIT_NS::TestFixture +{ + CPPUNIT_TEST_SUITE(WebStorageClientTest); + CPPUNIT_TEST(firstTest); +// CPPUNIT_TEST(getAllPlaylistsTest); +// CPPUNIT_TEST(deletePlaylistTest); +// CPPUNIT_TEST(createPlaylistTest); +// CPPUNIT_TEST(audioClipTest); +// CPPUNIT_TEST(acquireAudioClipTest); +// CPPUNIT_TEST(acquirePlaylistTest); + CPPUNIT_TEST_SUITE_END(); + + private: + /** + * The WebStorageClient instance to test. + */ + Ptr::Ref wsc; + + protected: + + /** + * A simple test. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + firstTest(void) throw (CPPUNIT_NS::Exception); + + /** + * Testing deletePlaylist(). + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + deletePlaylistTest(void) + throw (CPPUNIT_NS::Exception); + /** + * Testing getAllPlaylists(). + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + getAllPlaylistsTest(void) + throw (CPPUNIT_NS::Exception); + /** + * Testing createPlaylist(). + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + createPlaylistTest(void) throw (CPPUNIT_NS::Exception); + + /** + * Testing the audio clip operations. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + audioClipTest(void) throw (CPPUNIT_NS::Exception); + + /** + * Testing the acquire / release operations on audio clips. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + acquireAudioClipTest(void) throw (CPPUNIT_NS::Exception); + + /** + * Testing the acquire / release operations on playlists. + * + * @exception CPPUNIT_NS::Exception on test failures. + */ + void + acquirePlaylistTest(void) throw (CPPUNIT_NS::Exception); + + + public: + + /** + * Set up the environment for the test case. + */ + void + setUp(void) throw (); + + /** + * Clean up the environment after the test case. + */ + void + tearDown(void) throw (); +}; + + +/* ================================================= external data structures */ + + +/* ====================================================== function prototypes */ + + +} // namespace Storage +} // namespace LiveSupport + +#endif // WebStorageClientTest_h +