From fd32788092fcb29526ae73ae3bae6767dbb1e490 Mon Sep 17 00:00:00 2001 From: Cédric Bosdonnat Date: Mon, 4 Jun 2012 10:13:17 +0200 Subject: CMIS UCP: changed URLs to have hierarchical path Hierarchical path is assumed in loads of places, changed the URLs to the following: * Binding URL is encoded in the authority part, the repository ID is set as a fragment of the binding URL. * The hierarchical path reflects one of the path to the document on the server :x Change-Id: I8214daeb1d9c9b0f6ab86bdf60875e7e4e5369f4 --- ucb/source/ucp/cmis/cmis_content.cxx | 96 ++++++++++++++++++------------- ucb/source/ucp/cmis/cmis_content.hxx | 2 +- ucb/source/ucp/cmis/cmis_datasupplier.cxx | 10 +++- ucb/source/ucp/cmis/cmis_url.cxx | 87 ++++++++++++---------------- ucb/source/ucp/cmis/cmis_url.hxx | 14 ++--- 5 files changed, 106 insertions(+), 103 deletions(-) (limited to 'ucb') diff --git a/ucb/source/ucp/cmis/cmis_content.cxx b/ucb/source/ucp/cmis/cmis_content.cxx index d40deabb19f7..b25e1acf5ecc 100644 --- a/ucb/source/ucp/cmis/cmis_content.cxx +++ b/ucb/source/ucp/cmis/cmis_content.cxx @@ -171,7 +171,7 @@ namespace cmis pProvider->registerSession( url.getBindingUrl( ), m_pSession ); } - m_sObjectId = url.getObjectId( ); + m_sObjectPath = url.getObjectPath( ); m_sBindingUrl = url.getBindingUrl( ); } @@ -197,7 +197,7 @@ namespace cmis pProvider->registerSession( url.getBindingUrl( ), m_pSession ); } - m_sObjectId = url.getObjectId( ); + m_sObjectPath = url.getObjectPath( ); m_sBindingUrl = url.getBindingUrl( ); // Get the object type @@ -215,12 +215,12 @@ namespace cmis { if ( !m_pObject.get() ) { - if ( !m_sObjectId.isEmpty( ) ) - m_pObject = m_pSession->getObject( OUSTR_TO_STDSTR( m_sObjectId ) ); + if ( !m_sObjectPath.isEmpty( ) ) + m_pObject = m_pSession->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) ); else { m_pObject = m_pSession->getRootFolder( ); - m_sObjectId = rtl::OUString::createFromAscii( m_pObject->getId( ).c_str( ) ); + m_sObjectPath = "/"; } } } @@ -283,29 +283,48 @@ namespace cmis } else if ( rProp.Name == "Title" ) { - string name = getObject()->getName(); - xRow->appendString( rProp, rtl::OUString::createFromAscii( name.c_str() ) ); + rtl::OUString sTitle; + if ( getObject() ) + sTitle = rtl::OUString::createFromAscii( getObject()->getName().c_str( ) ); + else if ( m_pObjectProps.size() > 0 ) + { + map< string, libcmis::PropertyPtr >::iterator it = m_pObjectProps.find( "cmis:name" ); + if ( it != m_pObjectProps.end( ) ) + { + vector< string > values = it->second->getStrings( ); + if ( values.size() > 0 ) + sTitle = rtl::OUString::createFromAscii( values.front( ).c_str( ) ); + } + } + + // Nothing worked... get it from the path + if ( sTitle.isEmpty( ) ) + { + rtl::OUString sPath = m_sObjectPath; + + // Get rid of the trailing slash problem + if ( sPath[ sPath.getLength( ) - 1 ] == '/' ) + sPath = sPath.copy( 0, sPath.getLength() - 1 ); + + // Get the last segment + sal_Int32 nPos = sPath.lastIndexOf( '/' ); + if ( nPos > 0 ) + sTitle = sPath.copy( nPos + 1 ); + } + + if ( !sTitle.isEmpty( ) ) + xRow->appendString( rProp, sTitle ); + else + xRow->appendVoid( rProp ); } else if ( rProp.Name == "TitleOnServer" ) { string path; - libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject().get( ) ); - if ( NULL != document ) - { - vector< boost::shared_ptr< libcmis::Folder > > parents = document->getParents( ); - if ( parents.size() > 0 ) - path = parents.front( )->getPath( ); - - if ( path[ path.length() - 1 ] != '/' ) - path += "/"; - path += getObject()->getName( ); - } + vector< string > paths = getObject( )->getPaths( ); + if ( paths.size( ) > 0 ) + path = paths.front( ); else - { - libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject().get( ) ); - if ( NULL != folder ) - path = folder->getPath( ); - } + path = getObject()->getName( ); xRow->appendString( rProp, rtl::OUString::createFromAscii( path.c_str() ) ); } @@ -352,8 +371,8 @@ namespace cmis bool bExists = true; try { - if ( !m_sObjectId.isEmpty( ) ) - libcmis::ObjectPtr object = m_pSession->getObject( OUSTR_TO_STDSTR( m_sObjectId ) ); + if ( !m_sObjectPath.isEmpty( ) ) + m_pSession->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) ); // No need to handle the root folder case... how can it not exists? } catch ( const libcmis::Exception& ) @@ -479,7 +498,7 @@ namespace cmis // For transient content, the URL is the one of the parent if ( m_bTransient ) { - string sNewId; + rtl::OUString sNewPath; // Try to get the object from the server if there is any libcmis::Folder* pFolder = dynamic_cast< libcmis::Folder* >( getObject( ).get( ) ); @@ -503,7 +522,7 @@ namespace cmis try { object = m_pSession->getObjectByPath( newPath ); - sNewId = object->getId( ); + sNewPath = rtl::OUString::createFromAscii( newPath.c_str( ) ); } catch ( const libcmis::Exception& ) { @@ -540,7 +559,7 @@ namespace cmis if ( bIsFolder ) { libcmis::FolderPtr pNew = pFolder->createFolder( m_pObjectProps ); - sNewId = pNew->getId( ); + sNewPath = rtl::OUString::createFromAscii( newPath.c_str( ) ); } else { @@ -548,16 +567,16 @@ namespace cmis uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut ); copyData( xInputStream, xOutput ); libcmis::DocumentPtr pNew = pFolder->createDocument( m_pObjectProps, pOut, string() ); - sNewId = pNew->getId( ); + sNewPath = rtl::OUString::createFromAscii( newPath.c_str( ) ); } } - if ( !sNewId.empty( ) ) + if ( !sNewPath.isEmpty( ) ) { // Update the current content: it's no longer transient - m_sObjectId = rtl::OUString::createFromAscii( sNewId.c_str( ) ); + m_sObjectPath = sNewPath; URL aUrl( m_sURL ); - aUrl.setObjectId( m_sObjectId ); + aUrl.setObjectPath( m_sObjectPath ); m_sURL = aUrl.asString( ); m_pObject.reset( ); m_pObjectType.reset( ); @@ -790,8 +809,7 @@ namespace cmis SAL_INFO( "cmisucp", "Content::getParentURL()" ); - string parentId; - + string parentPath; try { libcmis::ObjectPtr pObj = getObject( ); @@ -800,25 +818,25 @@ namespace cmis { vector< boost::shared_ptr< libcmis::Folder > > parents = document->getParents( ); if ( parents.size( ) > 0 ) - parentId = parents.front( )->getId( ); + parentPath = parents.front( )->getPath( ); } else { libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject( ).get( ) ); if ( NULL != folder ) - parentId = folder->getFolderParent( )->getId( ); + parentPath = folder->getFolderParent( )->getPath( ); } } catch ( const libcmis::Exception & ) { // We may have an exception if we don't have the rights to - // get the parent ID + // get the parents } - if ( !parentId.empty() ) + if ( !parentPath.empty() ) { URL aUrl( m_sURL ); - aUrl.setObjectId( rtl::OUString::createFromAscii( parentId.c_str( ) ) ); + aUrl.setObjectPath( rtl::OUString::createFromAscii( parentPath.c_str( ) ) ); sRet = aUrl.asString( ); } diff --git a/ucb/source/ucp/cmis/cmis_content.hxx b/ucb/source/ucp/cmis/cmis_content.hxx index eafd5039503a..21ec1d19a954 100644 --- a/ucb/source/ucp/cmis/cmis_content.hxx +++ b/ucb/source/ucp/cmis/cmis_content.hxx @@ -71,7 +71,7 @@ private: ContentProvider* m_pProvider; libcmis::Session* m_pSession; libcmis::ObjectPtr m_pObject; - rtl::OUString m_sObjectId; + rtl::OUString m_sObjectPath; rtl::OUString m_sURL; rtl::OUString m_sBindingUrl; diff --git a/ucb/source/ucp/cmis/cmis_datasupplier.cxx b/ucb/source/ucp/cmis/cmis_datasupplier.cxx index 2a82a9bdfc4c..59ffd73ff609 100644 --- a/ucb/source/ucp/cmis/cmis_datasupplier.cxx +++ b/ucb/source/ucp/cmis/cmis_datasupplier.cxx @@ -90,11 +90,15 @@ namespace cmis if ( getResult( nIndex ) ) { - string sObjectId = maResults[nIndex]->pObject->getId( ); + string sObjectPath; + vector< string > paths = maResults[nIndex]->pObject->getPaths( ); + if ( paths.size( ) > 0 ) + sObjectPath = paths.front( ); + // TODO Handle the unfiled objects with their id... but can they manage to come here? - // Get the URL from the Id + // Get the URL from the Path URL aUrl( mxContent->getIdentifier( )->getContentIdentifier( ) ); - aUrl.setObjectId( rtl::OUString::createFromAscii( sObjectId.c_str( ) ) ); + aUrl.setObjectPath( rtl::OUString::createFromAscii( sObjectPath.c_str( ) ) ); rtl::OUString aId = aUrl.asString( ); maResults[ nIndex ]->aId = aId; diff --git a/ucb/source/ucp/cmis/cmis_url.cxx b/ucb/source/ucp/cmis/cmis_url.cxx index df225018d3a9..aed136b3d86a 100644 --- a/ucb/source/ucp/cmis/cmis_url.cxx +++ b/ucb/source/ucp/cmis/cmis_url.cxx @@ -28,6 +28,8 @@ #include +#include + #include "cmis_url.hxx" using namespace std; @@ -37,42 +39,24 @@ using namespace std; namespace cmis { - URL::URL( rtl::OUString const & urlStr ) : - m_aUrl( urlStr ) + URL::URL( rtl::OUString const & urlStr ) { + rtl::OUString sBindingUrl; + rtl::OUString sRepositoryId; + + INetURLObject aUrl( urlStr ); + + // Decode the authority to get the binding URL and repository id + rtl::OUString sDecodedHost = aUrl.GetHost( INetURLObject::DECODE_WITH_CHARSET ); + INetURLObject aHostUrl( sDecodedHost ); + m_sBindingUrl = aHostUrl.GetURLNoMark( ); + m_sRepositoryId = aHostUrl.GetMark( ); - rtl::OUString bindingUrl( "http://" ); - bindingUrl += m_aUrl.GetHostPort( ); - bindingUrl += m_aUrl.GetURLPath( ); - m_sBindingUrl = bindingUrl; - - // Split the query into bits and locate the repo-id key - rtl::OUString query = m_aUrl.GetParam( ); - while ( !query.isEmpty() ) - { - sal_Int32 nPos = query.indexOfAsciiL( "&", 1 ); - rtl::OUString segment; - if ( nPos > 0 ) - { - segment = query.copy( 0, nPos ); - query = query.copy( nPos + 1 ); - } - else - { - segment = query; - query = rtl::OUString(); - } - - sal_Int32 nEqPos = segment.indexOfAsciiL( "=", 1 ); - rtl::OUString key = segment.copy( 0, nEqPos ); - rtl::OUString value = segment.copy( nEqPos +1 ); - - if ( key == "repo-id" ) - m_sRepositoryId = value; - else - m_aQuery[key] = value; - } + m_sUser = aUrl.GetUser( ); + m_sPass = aUrl.GetPass( ); + // Store the path to the object + m_sPath = aUrl.GetURLPath( INetURLObject::DECODE_WITH_CHARSET ); } map< int, string > URL::getSessionParams( ) @@ -80,19 +64,15 @@ namespace cmis map< int, string > params; params[ATOMPUB_URL] = OUSTR_TO_STDSTR( m_sBindingUrl ); params[REPOSITORY_ID] = OUSTR_TO_STDSTR( m_sRepositoryId ); - params[USERNAME] = OUSTR_TO_STDSTR( m_aUrl.GetUser() ); - params[PASSWORD] = OUSTR_TO_STDSTR( m_aUrl.GetPass() ); + params[USERNAME] = OUSTR_TO_STDSTR( m_sUser ); + params[PASSWORD] = OUSTR_TO_STDSTR( m_sPass ); return params; } - rtl::OUString URL::getObjectId( ) + rtl::OUString URL::getObjectPath( ) { - rtl::OUString sResult; - map< rtl::OUString, rtl::OUString >::iterator it = m_aQuery.find( "id" ); - if ( it != m_aQuery.end( ) ) - sResult = it->second; - return sResult; + return m_sPath; } rtl::OUString URL::getBindingUrl( ) @@ -100,21 +80,26 @@ namespace cmis return m_sBindingUrl; } - void URL::setObjectId( rtl::OUString sId ) + void URL::setObjectPath( rtl::OUString sPath ) { - m_aQuery["id"] = sId; - updateUrlQuery( ); + m_sPath = sPath; } rtl::OUString URL::asString( ) { - return m_aUrl.GetMainURL( INetURLObject::NO_DECODE ); - } - - void URL::updateUrlQuery( ) - { - rtl::OUString sParam = "repo-id=" + m_sRepositoryId + "&id=" + m_aQuery["id"]; - m_aUrl.SetParam( sParam ); + rtl::OUString sUrl; + rtl::OUString sEncodedBinding = rtl::Uri::encode( + m_sBindingUrl + "#" + m_sRepositoryId, + rtl_UriCharClassUricNoSlash, + rtl_UriEncodeKeepEscapes, + RTL_TEXTENCODING_UTF8 ); + sUrl = "vnd.libreoffice.cmis+atom://" + sEncodedBinding; + + if ( m_sPath[0] != '/' ) + sUrl += "/"; + sUrl += m_sPath; + + return sUrl; } } diff --git a/ucb/source/ucp/cmis/cmis_url.hxx b/ucb/source/ucp/cmis/cmis_url.hxx index 18d13f166f37..833804b7e9f4 100644 --- a/ucb/source/ucp/cmis/cmis_url.hxx +++ b/ucb/source/ucp/cmis/cmis_url.hxx @@ -39,25 +39,21 @@ namespace cmis class URL { private: - INetURLObject m_aUrl; rtl::OUString m_sBindingUrl; rtl::OUString m_sRepositoryId; - - std::map< rtl::OUString, rtl::OUString > m_aQuery; + rtl::OUString m_sPath; + rtl::OUString m_sUser; + rtl::OUString m_sPass; public: URL( rtl::OUString const & urlStr ); std::map< int, std::string > getSessionParams( ); - rtl::OUString getObjectId( ); + rtl::OUString getObjectPath( ); rtl::OUString getBindingUrl( ); - void setObjectId( rtl::OUString sId ); + void setObjectPath( rtl::OUString sPath ); rtl::OUString asString( ); - - private: - - void updateUrlQuery( ); }; } -- cgit