diff options
author | Cédric Bosdonnat <cedric.bosdonnat@free.fr> | 2012-10-30 11:06:18 +0100 |
---|---|---|
committer | Cédric Bosdonnat <cedric.bosdonnat@free.fr> | 2012-10-31 12:03:30 +0100 |
commit | 1a9261124eed5baa04b069a1cb1b51f24423ec9b (patch) | |
tree | 1cb64575ef26bb2790e73b51371eff869f44cc13 /ucb | |
parent | 1eb7a921641107cdd802e8bbc6117d6f303f73f5 (diff) |
CMIS: added cancelCheckOut and checkIn implementations and menu items
Although the implementation is here, the dialogs to show when clicking
on the menu items aren't there yet.
Change-Id: I14886ec8ea8b97a35ca6c8474bc33e30da1a86d3
Diffstat (limited to 'ucb')
-rw-r--r-- | ucb/source/core/ucb.cxx | 15 | ||||
-rw-r--r-- | ucb/source/core/ucb.hxx | 5 | ||||
-rw-r--r-- | ucb/source/core/ucbcmds.cxx | 93 | ||||
-rw-r--r-- | ucb/source/core/ucbcmds.hxx | 3 | ||||
-rw-r--r-- | ucb/source/ucp/cmis/cmis_content.cxx | 288 | ||||
-rw-r--r-- | ucb/source/ucp/cmis/cmis_content.hxx | 11 |
6 files changed, 373 insertions, 42 deletions
diff --git a/ucb/source/core/ucb.cxx b/ucb/source/core/ucb.cxx index 568f530cb2d3..ee3926c639ad 100644 --- a/ucb/source/core/ucb.cxx +++ b/ucb/source/core/ucb.cxx @@ -679,6 +679,21 @@ Any SAL_CALL UniversalContentBroker::execute( globalTransfer( aTransferArg, Environment ); } + else if ( ( aCommand.Handle == CHECKIN_HANDLE ) || aCommand.Name == CHECKIN_NAME ) + { + ucb::CheckinArgument aCheckinArg; + if ( !( aCommand.Argument >>= aCheckinArg ) ) + { + ucbhelper::cancelCommandExecution( + makeAny( IllegalArgumentException( + OUString( "Wrong argument type!" ), + static_cast< cppu::OWeakObject * >( this ), + -1 ) ), + Environment ); + // Unreachable + } + aRet <<= checkIn( aCheckinArg, Environment ); + } else { ////////////////////////////////////////////////////////////////// diff --git a/ucb/source/core/ucb.hxx b/ucb/source/core/ucb.hxx index 9de5839aa08e..1f11b330c6af 100644 --- a/ucb/source/core/ucb.hxx +++ b/ucb/source/core/ucb.hxx @@ -21,6 +21,7 @@ #define _UCB_HXX +#include <com/sun/star/ucb/CheckinArgument.hpp> #include <com/sun/star/ucb/XUniversalContentBroker.hpp> #include <com/sun/star/lang/XInitialization.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -181,6 +182,10 @@ private: com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw( com::sun::star::uno::Exception ); + com::sun::star::uno::Any checkIn( const com::sun::star::ucb::CheckinArgument& rArg, + const com::sun::star::uno::Reference< + com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw( com::sun::star::uno::Exception ); + bool configureUcb() throw ( com::sun::star::uno::RuntimeException); diff --git a/ucb/source/core/ucbcmds.cxx b/ucb/source/core/ucbcmds.cxx index 975b53fc8bd0..043ceefbef8d 100644 --- a/ucb/source/core/ucbcmds.cxx +++ b/ucb/source/core/ucbcmds.cxx @@ -249,6 +249,13 @@ CommandProcessorInfo::CommandProcessorInfo() getCppuType( static_cast< ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType + (*m_pInfo)[ 2 ] + = ucb::CommandInfo( + rtl::OUString( CHECKIN_NAME ), // Name + CHECKIN_HANDLE, // Handle + getCppuType( + static_cast< + ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType } //========================================================================= @@ -1782,7 +1789,7 @@ void UniversalContentBroker::globalTransfer( try { ucb::Command aCommand( - rtl::OUString("transfer"), // Name + rtl::OUString( "transfer" ), // Name -1, // Handle uno::makeAny( aTransferArg ) ); // Argument @@ -2028,4 +2035,88 @@ void UniversalContentBroker::globalTransfer( } } +uno::Any UniversalContentBroker::checkIn( const ucb::CheckinArgument& rArg, + const uno::Reference< ucb::XCommandEnvironment >& xEnv ) throw ( uno::Exception ) +{ + uno::Any aRet; + // Use own command environment with own interaction handler intercepting + // some interaction requests that shall not be handled by the user-supplied + // interaction handler. + uno::Reference< ucb::XCommandEnvironment > xLocalEnv; + if (xEnv.is()) + { + uno::Reference< uno::XComponentContext > xCtx( + comphelper::getComponentContext( m_xSMgr ) ); + + xLocalEnv.set( ucb::CommandEnvironment::create( + xCtx, + new InteractionHandlerProxy( xEnv->getInteractionHandler() ), + xEnv->getProgressHandler() ) ); + } + + uno::Reference< ucb::XContent > xTarget; + uno::Reference< ucb::XContentIdentifier > xId + = createContentIdentifier( rArg.TargetURL ); + if ( xId.is() ) + { + try + { + xTarget = queryContent( xId ); + } + catch ( ucb::IllegalIdentifierException const & ) + { + } + } + + if ( !xTarget.is() ) + { + uno::Any aProps + = uno::makeAny(beans::PropertyValue( + rtl::OUString( "Uri" ), -1, + uno::makeAny( rArg.TargetURL ), + beans::PropertyState_DIRECT_VALUE ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >( &aProps, 1 ), + xEnv, + rtl::OUString( "Can't instanciate target object!" ), + this ); + // Unreachable + } + + uno::Reference< ucb::XCommandProcessor > xCommandProcessor( + xTarget, uno::UNO_QUERY ); + if ( !xCommandProcessor.is() ) + { + uno::Any aProps + = uno::makeAny( + beans::PropertyValue( + rtl::OUString( "Uri" ), -1, + uno::makeAny( rArg.TargetURL ), + beans::PropertyState_DIRECT_VALUE ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_CANT_READ, + uno::Sequence< uno::Any >( &aProps, 1 ), + xEnv, + rtl::OUString( "Target content is not a XCommandProcessor!" ), + this ); + // Unreachable + } + + try + { + ucb::Command aCommand( + rtl::OUString( "checkin" ), -1, + uno::makeAny( rArg ) ); + + aRet = xCommandProcessor->execute( aCommand, 0, xLocalEnv ); + } + catch ( ucb::UnsupportedCommandException const & ) + { + // 'checkin' command is not supported by commandprocessor: + // ignore. + } + return aRet; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/core/ucbcmds.hxx b/ucb/source/core/ucbcmds.hxx index 89b86f38e409..c0664f39705c 100644 --- a/ucb/source/core/ucbcmds.hxx +++ b/ucb/source/core/ucbcmds.hxx @@ -32,6 +32,9 @@ #define GLOBALTRANSFER_NAME "globalTransfer" #define GLOBALTRANSFER_HANDLE 1025 +#define CHECKIN_NAME "checkin" +#define CHECKIN_HANDLE 1026 + #endif /* !_UCBCMDS_HXX */ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/ucb/source/ucp/cmis/cmis_content.cxx b/ucb/source/ucp/cmis/cmis_content.cxx index 6ea78e0be528..0c6ba3625bc5 100644 --- a/ucb/source/ucp/cmis/cmis_content.cxx +++ b/ucb/source/ucp/cmis/cmis_content.cxx @@ -53,7 +53,9 @@ #include <libcmis/document.hxx> +#include <comphelper/processfactory.hxx> #include <ucbhelper/cancelcommandexecution.hxx> +#include <ucbhelper/content.hxx> #include <ucbhelper/contentidentifier.hxx> #include <ucbhelper/std_inputstream.hxx> #include <ucbhelper/std_outputstream.hxx> @@ -454,7 +456,8 @@ namespace cmis { boost::shared_ptr< libcmis::AllowableActions > allowableActions = getObject( xEnv )->getAllowableActions( ); sal_Bool bReadOnly = sal_False; - if ( !allowableActions->isAllowed( libcmis::ObjectAction::SetContentStream ) ) + if ( !allowableActions->isAllowed( libcmis::ObjectAction::SetContentStream ) && + !allowableActions->isAllowed( libcmis::ObjectAction::CheckIn ) ) bReadOnly = sal_True; xRow->appendBoolean( rProp, bReadOnly ); @@ -563,6 +566,60 @@ namespace cmis xRow->appendVoid( rProp ); } } + else if ( rProp.Name == "CanCheckOut" ) + { + try + { + libcmis::ObjectPtr pObject = getObject( xEnv ); + libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( ); + bool bAllowed = false; + if ( aAllowables ) + { + bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CheckOut ); + } + xRow->appendBoolean( rProp, bAllowed ); + } + catch ( const libcmis::Exception& ) + { + xRow->appendVoid( rProp ); + } + } + else if ( rProp.Name == "CanCancelCheckOut" ) + { + try + { + libcmis::ObjectPtr pObject = getObject( xEnv ); + libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( ); + bool bAllowed = false; + if ( aAllowables ) + { + bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CancelCheckOut ); + } + xRow->appendBoolean( rProp, bAllowed ); + } + catch ( const libcmis::Exception& ) + { + xRow->appendVoid( rProp ); + } + } + else if ( rProp.Name == "CanCheckIn" ) + { + try + { + libcmis::ObjectPtr pObject = getObject( xEnv ); + libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( ); + bool bAllowed = false; + if ( aAllowables ) + { + bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CheckIn ); + } + xRow->appendBoolean( rProp, bAllowed ); + } + catch ( const libcmis::Exception& ) + { + xRow->appendVoid( rProp ); + } + } else SAL_INFO( "cmisucp", "Looking for unsupported property " << rProp.Name ); } @@ -662,6 +719,170 @@ namespace cmis return aRet; } + rtl::OUString Content::checkIn( const ucb::CheckinArgument& rArg, + const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) + { + ucbhelper::Content aSourceContent( rArg.SourceURL, xEnv, comphelper::getProcessComponentContext( ) ); + uno::Reference< io::XInputStream > xIn = aSourceContent.openStream( ); + + libcmis::ObjectPtr object; + try + { + object = getObject( xEnv ); + } + catch ( const libcmis::Exception& ) + { + } + + libcmis::Document* pPwc = dynamic_cast< libcmis::Document* >( object.get( ) ); + if ( !pPwc ) + { + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_GENERAL, + uno::Sequence< uno::Any >( 0 ), + xEnv, + "Checkin only supported by documents" ); + } + + boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) ); + uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut ); + copyData( xIn, xOutput ); + + map< string, libcmis::PropertyPtr > newProperties; + libcmis::DocumentPtr pDoc = pPwc->checkIn( rArg.MajorVersion, OUSTR_TO_STDSTR( rArg.VersionComment ), newProperties, + pOut, OUSTR_TO_STDSTR( rArg.MimeType ), OUSTR_TO_STDSTR( rArg.NewTitle ) ); + + // Get the URL and send it back as a result + URL aCmisUrl( m_sURL ); + vector< string > aPaths = pDoc->getPaths( ); + if ( !aPaths.empty() ) + { + string sPath = aPaths.front( ); + aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) ); + } + else + { + // We may have unfiled document depending on the server, those + // won't have any path, use their ID instead + string sId = pDoc->getId( ); + aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) ); + } + return aCmisUrl.asString( ); + } + + rtl::OUString Content::checkOut( const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) + { + rtl::OUString aRet; + try + { + // Checkout the document if possible + libcmis::DocumentPtr pDoc = boost::dynamic_pointer_cast< libcmis::Document >( getObject( xEnv ) ); + if ( pDoc.get( ) == NULL ) + { + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_GENERAL, + uno::Sequence< uno::Any >( 0 ), + xEnv, + "Checkout only supported by documents" ); + } + libcmis::DocumentPtr pPwc = pDoc->checkOut( ); + + // Compute the URL of the Private Working Copy (PWC) + URL aCmisUrl( m_sURL ); + vector< string > aPaths = pPwc->getPaths( ); + if ( !aPaths.empty() ) + { + string sPath = aPaths.front( ); + aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) ); + } + else + { + // We may have unfiled PWC depending on the server, those + // won't have any path, use their ID instead + string sId = pPwc->getId( ); + aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) ); + } + aRet = aCmisUrl.asString( ); + } + catch ( const libcmis::Exception& e ) + { + SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_GENERAL, + uno::Sequence< uno::Any >( 0 ), + xEnv, + rtl::OUString::createFromAscii( e.what() ) ); + } + return aRet; + } + + rtl::OUString Content::cancelCheckOut( const uno::Reference< ucb::XCommandEnvironment > & xEnv ) + throw( uno::Exception ) + { + rtl::OUString aRet; + try + { + libcmis::DocumentPtr pPwc = boost::dynamic_pointer_cast< libcmis::Document >( getObject( xEnv ) ); + if ( pPwc.get( ) == NULL ) + { + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_GENERAL, + uno::Sequence< uno::Any >( 0 ), + xEnv, + "CancelCheckout only supported by documents" ); + } + pPwc->cancelCheckout( ); + + // Get the Original document (latest version) + vector< libcmis::DocumentPtr > aVersions = pPwc->getAllVersions( ); + libcmis::DocumentPtr pDoc; + for ( vector< libcmis::DocumentPtr >::iterator it = aVersions.begin(); + it != aVersions.end( ) && pDoc != NULL; ++it ) + { + libcmis::DocumentPtr pVersion = *it; + map< string, libcmis::PropertyPtr > aProps = pVersion->getProperties( ); + bool bIsLatestVersion = false; + map< string, libcmis::PropertyPtr >::iterator propIt = aProps.find( string( "cmis:isLatestVersion" ) ); + if ( propIt != aProps.end( ) && !propIt->second->getBools( ).empty( ) ) + { + bIsLatestVersion = propIt->second->getBools( ).front( ); + } + + if ( bIsLatestVersion ) + pDoc.reset( pVersion.get( ) ); + } + + // Compute the URL of the Document + URL aCmisUrl( m_sURL ); + vector< string > aPaths = pDoc->getPaths( ); + if ( !aPaths.empty() ) + { + string sPath = aPaths.front( ); + aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) ); + } + else + { + // We may have unfiled doc depending on the server, those + // won't have any path, use their ID instead + string sId = pDoc->getId( ); + aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) ); + } + aRet = aCmisUrl.asString( ); + } + catch ( const libcmis::Exception& e ) + { + SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) ); + ucbhelper::cancelCommandExecution( + ucb::IOErrorCode_GENERAL, + uno::Sequence< uno::Any >( 0 ), + xEnv, + rtl::OUString::createFromAscii( e.what() ) ); + } + return aRet; + } + void Content::transfer( const ucb::TransferInfo& rTransferInfo, const uno::Reference< ucb::XCommandEnvironment > & xEnv ) throw( uno::Exception ) @@ -756,11 +977,10 @@ namespace cmis libcmis::Document* document = dynamic_cast< libcmis::Document* >( object.get( ) ); if ( NULL != document ) { - string sMime = document->getContentType( ); boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) ); uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut ); copyData( xInputStream, xOutput ); - document->setContentStream( pOut, sMime, OUSTR_TO_STDSTR( rMimeType ), bReplaceExisting ); + document->setContentStream( pOut, OUSTR_TO_STDSTR( rMimeType ), string( ), bReplaceExisting ); } } else @@ -997,6 +1217,15 @@ namespace cmis beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVersionable" ) ), -1, getCppuBooleanType(), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCheckOut" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCancelCheckOut" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), + beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCheckIn" ) ), + -1, getCppuBooleanType(), + beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ), }; const int nProps = SAL_N_ELEMENTS(aGenericProperties); @@ -1035,6 +1264,9 @@ namespace cmis // Mandatory CMIS-only commands ucb::CommandInfo ( rtl::OUString( "checkout" ), -1, getCppuVoidType() ), + ucb::CommandInfo ( rtl::OUString( "cancelCheckout" ), -1, getCppuVoidType() ), + ucb::CommandInfo ( rtl::OUString( "checkIn" ), -1, + getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ), // Folder Only, omitted if not a folder ucb::CommandInfo @@ -1227,46 +1459,20 @@ namespace cmis } else if ( aCommand.Name == "checkout" ) { - try - { - // Checkout the document if possible - libcmis::DocumentPtr pDoc = boost::dynamic_pointer_cast< libcmis::Document >( getObject( xEnv ) ); - if ( pDoc.get( ) == NULL ) - { - ucbhelper::cancelCommandExecution( - ucb::IOErrorCode_GENERAL, - uno::Sequence< uno::Any >( 0 ), - xEnv, - "Checkout only supported by documents" ); - } - libcmis::DocumentPtr pPwc = pDoc->checkOut( ); - - // Compute the URL of the Private Working Copy (PWC) - URL aCmisUrl( m_sURL ); - vector< string > aPaths = pPwc->getPaths( ); - if ( !aPaths.empty() ) - { - string sPath = aPaths.front( ); - aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) ); - } - else - { - // We may have unfiled PWC depending on the server, those - // won't have any path, use their ID instead - string sId = pPwc->getId( ); - aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) ); - } - aRet <<= aCmisUrl.asString( ); - } - catch ( const libcmis::Exception& e ) + aRet <<= checkOut( xEnv ); + } + else if ( aCommand.Name == "cancelCheckout" ) + { + aRet <<= cancelCheckOut( xEnv ); + } + else if ( aCommand.Name == "checkin" ) + { + ucb::CheckinArgument aArg; + if ( !( aCommand.Argument >>= aArg ) ) { - SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) ); - ucbhelper::cancelCommandExecution( - ucb::IOErrorCode_GENERAL, - uno::Sequence< uno::Any >( 0 ), - xEnv, - rtl::OUString::createFromAscii( e.what() ) ); + ucbhelper::cancelCommandExecution ( getBadArgExcept(), xEnv ); } + aRet <<= checkIn( aArg, xEnv ); } else { diff --git a/ucb/source/ucp/cmis/cmis_content.hxx b/ucb/source/ucp/cmis/cmis_content.hxx index 8790834ed0cd..42c8482a28fb 100644 --- a/ucb/source/ucp/cmis/cmis_content.hxx +++ b/ucb/source/ucp/cmis/cmis_content.hxx @@ -34,6 +34,7 @@ #include <com/sun/star/io/XInputStream.hpp> #include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/ucb/CheckinArgument.hpp> #include <com/sun/star/ucb/ContentCreationException.hpp> #include <com/sun/star/ucb/OpenCommandArgument2.hpp> #include <com/sun/star/ucb/TransferInfo.hpp> @@ -117,6 +118,16 @@ private: const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment >& xEnv ) throw( com::sun::star::uno::Exception ); + rtl::OUString checkIn( const com::sun::star::ucb::CheckinArgument& rArg, + const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( com::sun::star::uno::Exception ); + + rtl::OUString checkOut( const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( com::sun::star::uno::Exception ); + + rtl::OUString cancelCheckOut( const com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv ) + throw( com::sun::star::uno::Exception ); + void destroy( ) throw( com::sun::star::uno::Exception ); void copyData( com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xIn, |