1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 #include <com/sun/star/beans/PropertyAttribute.hpp>
13 #include <com/sun/star/beans/PropertyValue.hpp>
14 #include <com/sun/star/beans/PropertyValues.hpp>
15 #include <com/sun/star/beans/XPropertySetInfo.hpp>
16 #include <com/sun/star/document/CmisProperty.hpp>
17 #include <com/sun/star/io/XActiveDataSink.hpp>
18 #include <com/sun/star/io/XActiveDataStreamer.hpp>
19 #include <com/sun/star/lang/IllegalAccessException.hpp>
20 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
21 #include <com/sun/star/task/InteractionClassification.hpp>
22 #include <com/sun/star/ucb/ContentInfo.hpp>
23 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
24 #include <com/sun/star/ucb/InsertCommandArgument2.hpp>
25 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
26 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
27 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
28 #include <com/sun/star/ucb/NameClash.hpp>
29 #include <com/sun/star/ucb/NameClashException.hpp>
30 #include <com/sun/star/ucb/OpenMode.hpp>
31 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
32 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
33 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
34 #include <com/sun/star/ucb/XCommandInfo.hpp>
35 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
37 #include <com/sun/star/xml/crypto/XDigestContext.hpp>
38 #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp>
39 #include <com/sun/star/xml/crypto/DigestID.hpp>
40 #include <com/sun/star/xml/crypto/NSSInitializer.hpp>
43 #include <comphelper/processfactory.hxx>
44 #include <cppuhelper/exc_hlp.hxx>
45 #include <config_oauth2.h>
46 #include <ucbhelper/cancelcommandexecution.hxx>
47 #include <ucbhelper/content.hxx>
48 #include <ucbhelper/contentidentifier.hxx>
49 #include <ucbhelper/std_inputstream.hxx>
50 #include <ucbhelper/std_outputstream.hxx>
51 #include <ucbhelper/propertyvalueset.hxx>
52 #include <ucbhelper/proxydecider.hxx>
53 #include <sax/tools/converter.hxx>
55 #include "auth_provider.hxx"
56 #include "certvalidation_handler.hxx"
57 #include "cmis_content.hxx"
58 #include "cmis_provider.hxx"
59 #include "cmis_resultset.hxx"
60 #include "cmis_strings.hxx"
62 #define OUSTR_TO_STDSTR(s) string( OUStringToOString( s, RTL_TEXTENCODING_UTF8 ).getStr() )
63 #define STD_TO_OUSTR( str ) OUString( str.c_str(), str.length( ), RTL_TEXTENCODING_UTF8 )
65 using namespace com::sun::star
;
70 util::DateTime
lcl_boostToUnoTime(const boost::posix_time::ptime
& boostTime
)
72 util::DateTime unoTime
;
73 unoTime
.Year
= boostTime
.date().year();
74 unoTime
.Month
= boostTime
.date().month();
75 unoTime
.Day
= boostTime
.date().day();
76 unoTime
.Hours
= boostTime
.time_of_day().hours();
77 unoTime
.Minutes
= boostTime
.time_of_day().minutes();
78 unoTime
.Seconds
= boostTime
.time_of_day().seconds();
80 // TODO FIXME maybe we should compile with BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG
81 // to actually get nanosecond precision in boostTime?
82 // use this way rather than total_nanos to avoid overflows with 32-bit long
83 const long ticks
= boostTime
.time_of_day().fractional_seconds();
84 long nanoSeconds
= ticks
* ( 1000000000 / boost::posix_time::time_duration::ticks_per_second());
86 unoTime
.NanoSeconds
= nanoSeconds
;
91 uno::Any
lcl_cmisPropertyToUno( libcmis::PropertyPtr pProperty
)
94 switch ( pProperty
->getPropertyType( )->getType( ) )
97 case libcmis::PropertyType::String
:
99 vector
< string
> aCmisStrings
= pProperty
->getStrings( );
100 uno::Sequence
< OUString
> aStrings( aCmisStrings
.size( ) );
101 OUString
* aStringsArr
= aStrings
.getArray( );
103 for ( vector
< string
>::iterator it
= aCmisStrings
.begin( );
104 it
!= aCmisStrings
.end( ); ++it
, ++i
)
107 aStringsArr
[i
] = STD_TO_OUSTR( str
);
112 case libcmis::PropertyType::Integer
:
114 vector
< long > aCmisLongs
= pProperty
->getLongs( );
115 uno::Sequence
< sal_Int64
> aLongs( aCmisLongs
.size( ) );
116 sal_Int64
* aLongsArr
= aLongs
.getArray( );
118 for ( vector
< long >::iterator it
= aCmisLongs
.begin( );
119 it
!= aCmisLongs
.end( ); ++it
, ++i
)
126 case libcmis::PropertyType::Decimal
:
128 vector
< double > aCmisDoubles
= pProperty
->getDoubles( );
129 uno::Sequence
< double > aDoubles( aCmisDoubles
.size( ) );
130 double* aDoublesArr
= aDoubles
.getArray( );
132 for ( vector
< double >::iterator it
= aCmisDoubles
.begin( );
133 it
!= aCmisDoubles
.end( ); ++it
, ++i
)
135 aDoublesArr
[i
] = *it
;
140 case libcmis::PropertyType::Bool
:
142 vector
< bool > aCmisBools
= pProperty
->getBools( );
143 uno::Sequence
< sal_Bool
> aBools( aCmisBools
.size( ) );
144 sal_Bool
* aBoolsArr
= aBools
.getArray( );
146 for ( vector
< bool >::iterator it
= aCmisBools
.begin( );
147 it
!= aCmisBools
.end( ); ++it
, ++i
)
154 case libcmis::PropertyType::DateTime
:
156 vector
< boost::posix_time::ptime
> aCmisTimes
= pProperty
->getDateTimes( );
157 uno::Sequence
< util::DateTime
> aTimes( aCmisTimes
.size( ) );
158 util::DateTime
* aTimesArr
= aTimes
.getArray( );
160 for ( vector
< boost::posix_time::ptime
>::iterator it
= aCmisTimes
.begin( );
161 it
!= aCmisTimes
.end( ); ++it
, ++i
)
163 aTimesArr
[i
] = lcl_boostToUnoTime( *it
);
172 libcmis::PropertyPtr
lcl_unoToCmisProperty(const document::CmisProperty
& prop
)
174 libcmis::PropertyTypePtr
propertyType( new libcmis::PropertyType( ) );
176 OUString id
= prop
.Id
;
177 OUString name
= prop
.Name
;
178 bool bUpdatable
= prop
.Updatable
;
179 bool bRequired
= prop
.Required
;
180 bool bMultiValued
= prop
.MultiValued
;
181 bool bOpenChoice
= prop
.OpenChoice
;
182 uno::Any value
= prop
.Value
;
183 std::vector
< std::string
> values
;
185 libcmis::PropertyType::Type type
= libcmis::PropertyType::String
;
186 if ( prop
.Type
== CMIS_TYPE_STRING
)
188 uno::Sequence
< OUString
> seqValue
;
190 sal_Int32 m_nNumValue
= seqValue
.getLength( );
191 for ( sal_Int32 i
= 0; i
< m_nNumValue
; ++i
)
193 values
.push_back( OUSTR_TO_STDSTR( seqValue
[i
] ) );
195 type
= libcmis::PropertyType::String
;
197 else if ( prop
.Type
== CMIS_TYPE_BOOL
)
199 uno::Sequence
< sal_Bool
> seqValue
;
201 sal_Int32 m_nNumValue
= seqValue
.getLength( );
202 for ( sal_Int32 i
= 0; i
< m_nNumValue
; ++i
)
204 values
.push_back( OUSTR_TO_STDSTR( OUString::boolean( seqValue
[i
] ) ) );
206 type
= libcmis::PropertyType::Bool
;
208 else if ( prop
.Type
== CMIS_TYPE_INTEGER
)
210 uno::Sequence
< sal_Int64
> seqValue
;
212 sal_Int32 m_nNumValue
= seqValue
.getLength( );
213 for ( sal_Int32 i
= 0; i
< m_nNumValue
; ++i
)
215 values
.push_back( OUSTR_TO_STDSTR( OUString::number( seqValue
[i
] ) ) );
217 type
= libcmis::PropertyType::Integer
;
219 else if ( prop
.Type
== CMIS_TYPE_DECIMAL
)
221 uno::Sequence
< double > seqValue
;
223 sal_Int32 m_nNumValue
= seqValue
.getLength( );
224 for ( sal_Int32 i
= 0; i
< m_nNumValue
; ++i
)
226 values
.push_back( OUSTR_TO_STDSTR( OUString::number( seqValue
[i
] ) ) );
228 type
= libcmis::PropertyType::Decimal
;
230 else if ( prop
.Type
== CMIS_TYPE_DATETIME
)
232 uno::Sequence
< util::DateTime
> seqValue
;
234 sal_Int32 m_nNumValue
= seqValue
.getLength( );
235 for ( sal_Int32 i
= 0; i
< m_nNumValue
; ++i
)
237 OUStringBuffer aBuffer
;
238 ::sax::Converter::convertDateTime( aBuffer
, seqValue
[i
], 0, false );
239 values
.push_back( OUSTR_TO_STDSTR( aBuffer
.makeStringAndClear( ) ) );
241 type
= libcmis::PropertyType::DateTime
;
244 propertyType
->setId( OUSTR_TO_STDSTR( id
));
245 propertyType
->setDisplayName( OUSTR_TO_STDSTR( name
) );
246 propertyType
->setUpdatable( bUpdatable
);
247 propertyType
->setRequired( bRequired
);
248 propertyType
->setMultiValued( bMultiValued
);
249 propertyType
->setOpenChoice( bOpenChoice
);
250 propertyType
->setType( type
);
252 libcmis::PropertyPtr
property( new libcmis::Property( propertyType
, values
) );
260 Content::Content( const uno::Reference
< uno::XComponentContext
>& rxContext
,
261 ContentProvider
*pProvider
, const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
262 libcmis::ObjectPtr pObject
)
263 throw ( ucb::ContentCreationException
)
264 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
265 m_pProvider( pProvider
),
267 m_pObject( pObject
),
268 m_sURL( Identifier
->getContentIdentifier( ) ),
269 m_aURL( Identifier
->getContentIdentifier( ) ),
270 m_bTransient( false ),
273 SAL_INFO( "ucb.ucp.cmis", "Content::Content() " << m_sURL
);
275 m_sObjectPath
= m_aURL
.getObjectPath( );
276 m_sObjectId
= m_aURL
.getObjectId( );
279 Content::Content( const uno::Reference
< uno::XComponentContext
>& rxContext
, ContentProvider
*pProvider
,
280 const uno::Reference
< ucb::XContentIdentifier
>& Identifier
,
282 throw ( ucb::ContentCreationException
)
283 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
284 m_pProvider( pProvider
),
286 m_sURL( Identifier
->getContentIdentifier( ) ),
287 m_aURL( Identifier
->getContentIdentifier( ) ),
288 m_bTransient( true ),
289 m_bIsFolder( bIsFolder
)
291 SAL_INFO( "ucb.ucp.cmis", "Content::Content() " << m_sURL
);
293 m_sObjectPath
= m_aURL
.getObjectPath( );
294 m_sObjectId
= m_aURL
.getObjectId( );
301 libcmis::Session
* Content::getSession( const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
303 // Set the proxy if needed. We are doing that all times as the proxy data shouldn't be cached.
304 ucbhelper::InternetProxyDecider
aProxyDecider( m_xContext
);
305 INetURLObject
aBindingUrl( m_aURL
.getBindingUrl( ) );
306 const ucbhelper::InternetProxyServer
& rProxy
= aProxyDecider
.getProxy(
307 INetURLObject::GetScheme( aBindingUrl
.GetProtocol( ) ), aBindingUrl
.GetHost(), aBindingUrl
.GetPort() );
308 OUString sProxy
= rProxy
.aName
;
309 if ( rProxy
.nPort
> 0 )
310 sProxy
+= ":" + OUString::number( rProxy
.nPort
);
311 libcmis::SessionFactory::setProxySettings( OUSTR_TO_STDSTR( sProxy
), string(), string(), string() );
313 // Look for a cached session, key is binding url + repo id
314 OUString sSessionId
= m_aURL
.getBindingUrl( ) + m_aURL
.getRepositoryId( );
315 if ( NULL
== m_pSession
)
316 m_pSession
= m_pProvider
->getSession( sSessionId
);
318 if ( NULL
== m_pSession
)
321 // Initialize NSS library to make sure libcmis (and curl) can access CACERTs using NSS
322 // when using internal libcurl.
323 uno::Reference
< com::sun::star::xml::crypto::XNSSInitializer
>
324 xNSSInitializer
= com::sun::star::xml::crypto::NSSInitializer::create( m_xContext
);
326 uno::Reference
< com::sun::star::xml::crypto::XDigestContext
> xDigestContext(
327 xNSSInitializer
->getDigestContext( com::sun::star::xml::crypto::DigestID::SHA256
,
328 uno::Sequence
< beans::NamedValue
>() ),
329 uno::UNO_SET_THROW
);
332 // Set the SSL Validation handler
333 libcmis::CertValidationHandlerPtr
certHandler(
334 new CertValidationHandler( xEnv
, m_xContext
, aBindingUrl
.GetHost( ) ) );
335 libcmis::SessionFactory::setCertificateValidationHandler( certHandler
);
337 // Get the auth credentials
338 AuthProvider
authProvider( xEnv
, m_xIdentifier
->getContentIdentifier( ), m_aURL
.getBindingUrl( ) );
339 AuthProvider::setXEnv( xEnv
);
341 string rUsername
= OUSTR_TO_STDSTR( m_aURL
.getUsername( ) );
342 string rPassword
= OUSTR_TO_STDSTR( m_aURL
.getPassword( ) );
343 if ( authProvider
.authenticationQuery( rUsername
, rPassword
) )
345 // Initiate a CMIS session and register it as we found nothing
346 libcmis::OAuth2DataPtr oauth2Data
;
347 if ( m_aURL
.getBindingUrl( ) == GDRIVE_BASE_URL
)
348 oauth2Data
.reset( new libcmis::OAuth2Data(
349 GDRIVE_AUTH_URL
, GDRIVE_TOKEN_URL
,
350 GDRIVE_SCOPE
, GDRIVE_REDIRECT_URI
,
351 GDRIVE_CLIENT_ID
, GDRIVE_CLIENT_SECRET
) );
352 if ( m_aURL
.getBindingUrl().startsWith( ALFRESCO_CLOUD_BASE_URL
) )
353 oauth2Data
.reset( new libcmis::OAuth2Data(
354 ALFRESCO_CLOUD_AUTH_URL
, ALFRESCO_CLOUD_TOKEN_URL
,
355 ALFRESCO_CLOUD_SCOPE
, ALFRESCO_CLOUD_REDIRECT_URI
,
356 ALFRESCO_CLOUD_CLIENT_ID
, ALFRESCO_CLOUD_CLIENT_SECRET
) );
357 if ( m_aURL
.getBindingUrl( ) == ONEDRIVE_BASE_URL
)
359 libcmis::SessionFactory::setOAuth2AuthCodeProvider( authProvider
.onedriveAuthCodeFallback
);
360 oauth2Data
.reset( new libcmis::OAuth2Data(
361 ONEDRIVE_AUTH_URL
, ONEDRIVE_TOKEN_URL
,
362 ONEDRIVE_SCOPE
, ONEDRIVE_REDIRECT_URI
,
363 ONEDRIVE_CLIENT_ID
, ONEDRIVE_CLIENT_SECRET
) );
365 m_pSession
= libcmis::SessionFactory::createSession(
366 OUSTR_TO_STDSTR( m_aURL
.getBindingUrl( ) ),
367 rUsername
, rPassword
, OUSTR_TO_STDSTR( m_aURL
.getRepositoryId( ) ), false, oauth2Data
);
368 if ( m_pSession
== NULL
)
369 ucbhelper::cancelCommandExecution(
370 ucb::IOErrorCode_INVALID_DEVICE
,
371 uno::Sequence
< uno::Any
>( 0 ),
375 m_pProvider
->registerSession( sSessionId
, m_pSession
);
379 // Silently fail as the user cancelled the authentication
380 throw uno::RuntimeException( );
386 libcmis::ObjectTypePtr
Content::getObjectType( const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
388 if ( NULL
== m_pObjectType
.get( ) && m_bTransient
)
390 string typeId
= m_bIsFolder
? "cmis:folder" : "cmis:document";
391 // The type to create needs to be fetched from the possible children types
392 // defined in the parent folder. Then, we'll pick up the first one we find matching
393 // cmis:folder or cmis:document (depending what we need to create).
394 // The easy case will work in most cases, but not on some servers (like Lotus Live)
395 libcmis::Folder
* pParent
= NULL
;
396 bool bTypeRestricted
= false;
399 pParent
= dynamic_cast< libcmis::Folder
* >( getObject( xEnv
).get( ) );
401 catch ( const libcmis::Exception
& )
407 map
< string
, libcmis::PropertyPtr
>& aProperties
= pParent
->getProperties( );
408 map
< string
, libcmis::PropertyPtr
>::iterator it
= aProperties
.find( "cmis:allowedChildObjectTypeIds" );
409 if ( it
!= aProperties
.end( ) )
411 libcmis::PropertyPtr pProperty
= it
->second
;
414 vector
< string
> typesIds
= pProperty
->getStrings( );
415 for ( vector
< string
>::iterator typeIt
= typesIds
.begin();
416 typeIt
!= typesIds
.end() && !m_pObjectType
; ++typeIt
)
418 bTypeRestricted
= true;
419 libcmis::ObjectTypePtr type
= getSession( xEnv
)->getType( *typeIt
);
421 // FIXME Improve performances by adding getBaseTypeId( ) method to libcmis
422 if ( type
->getBaseType( )->getId( ) == typeId
)
423 m_pObjectType
= type
;
429 if ( !bTypeRestricted
)
430 m_pObjectType
= getSession( xEnv
)->getType( typeId
);
432 return m_pObjectType
;
436 libcmis::ObjectPtr
Content::getObject( const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
) throw (css::uno::RuntimeException
, css::ucb::CommandFailedException
, libcmis::Exception
)
438 // can't get the session for some reason
439 // the recent file openning at start up is an example.
442 if ( !getSession( xEnv
) )
445 catch ( uno::RuntimeException
& )
449 if ( !m_pObject
.get() )
451 if ( !m_sObjectId
.isEmpty( ) )
455 m_pObject
= getSession( xEnv
)->getObject( OUSTR_TO_STDSTR( m_sObjectId
) );
457 catch ( const libcmis::Exception
& )
459 throw libcmis::Exception( "Object not found" );
462 else if ( !m_sObjectPath
.isEmpty( ) )
466 m_pObject
= getSession( xEnv
)->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath
) );
468 catch ( const libcmis::Exception
& )
470 // In some cases, getting the object from the path doesn't work,
471 // but getting the parent from its path and the get the child in the list is OK.
472 // It's weird, but needed to handle case where the path isn't the folders/files
473 // names separated by '/' (as in Lotus Live)
474 INetURLObject
aParentUrl( m_sURL
);
475 string sName
= OUSTR_TO_STDSTR( aParentUrl
.getName( INetURLObject::LAST_SEGMENT
, true, INetURLObject::DECODE_WITH_CHARSET
) );
476 aParentUrl
.removeSegment( );
477 OUString sParentUrl
= aParentUrl
.GetMainURL( INetURLObject::NO_DECODE
);
479 Content
aParent( m_xContext
, m_pProvider
, new ucbhelper::ContentIdentifier( sParentUrl
) );
480 libcmis::FolderPtr pParentFolder
= boost::dynamic_pointer_cast
< libcmis::Folder
>( aParent
.getObject( xEnv
) );
483 vector
< libcmis::ObjectPtr
> children
= pParentFolder
->getChildren( );
484 for ( vector
< libcmis::ObjectPtr
>::iterator it
= children
.begin( );
485 it
!= children
.end() && !m_pObject
; ++it
)
487 if ( ( *it
)->getName( ) == sName
)
493 throw libcmis::Exception( "Object not found" );
498 m_pObject
= getSession( xEnv
)->getRootFolder( );
500 m_sObjectId
= OUString( );
507 bool Content::isFolder(const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
509 bool bIsFolder
= false;
512 libcmis::ObjectPtr obj
= getObject( xEnv
);
514 bIsFolder
= obj
->getBaseType( ) == "cmis:folder";
516 catch ( const libcmis::Exception
& e
)
518 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
519 ucbhelper::cancelCommandExecution(
520 ucb::IOErrorCode_GENERAL
,
521 uno::Sequence
< uno::Any
>( 0 ),
523 OUString::createFromAscii( e
.what( ) ) );
528 uno::Any
Content::getBadArgExcept()
530 return uno::makeAny( lang::IllegalArgumentException(
531 OUString("Wrong argument type!"),
532 static_cast< cppu::OWeakObject
* >( this ), -1) );
535 libcmis::ObjectPtr
Content::updateProperties(
536 const uno::Any
& iCmisProps
,
537 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
539 // Convert iCmisProps to Cmis Properties;
540 uno::Sequence
< document::CmisProperty
> aPropsSeq
;
541 iCmisProps
>>= aPropsSeq
;
542 map
< string
, libcmis::PropertyPtr
> aProperties
;
544 sal_Int32 propsLen
= aPropsSeq
.getLength( );
545 for ( sal_Int32 i
= 0; i
< propsLen
; i
++ )
547 std::string id
= OUSTR_TO_STDSTR( aPropsSeq
[i
].Id
);
548 libcmis::PropertyPtr prop
= lcl_unoToCmisProperty( aPropsSeq
[i
] );
549 aProperties
.insert( std::pair
<string
, libcmis::PropertyPtr
>( id
, prop
) );
551 libcmis::ObjectPtr updateObj
;
554 updateObj
= getObject( xEnv
)->updateProperties( aProperties
);
556 catch ( const libcmis::Exception
& e
)
558 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: "<< e
.what( ) );
564 uno::Reference
< sdbc::XRow
> Content::getPropertyValues(
565 const uno::Sequence
< beans::Property
>& rProperties
,
566 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
568 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
= new ::ucbhelper::PropertyValueSet( m_xContext
);
571 const beans::Property
* pProps
;
573 nProps
= rProperties
.getLength();
574 pProps
= rProperties
.getConstArray();
576 for( sal_Int32 n
= 0; n
< nProps
; ++n
)
578 const beans::Property
& rProp
= pProps
[ n
];
582 if ( rProp
.Name
== "IsDocument" )
586 libcmis::ObjectPtr obj
= getObject( xEnv
);
588 xRow
->appendBoolean( rProp
, obj
->getBaseType( ) == "cmis:document" );
590 catch ( const libcmis::Exception
& )
592 if ( m_pObjectType
.get( ) )
593 xRow
->appendBoolean( rProp
, getObjectType( xEnv
)->getBaseType()->getId( ) == "cmis:document" );
595 xRow
->appendVoid( rProp
);
598 else if ( rProp
.Name
== "IsFolder" )
602 libcmis::ObjectPtr obj
= getObject( xEnv
);
604 xRow
->appendBoolean( rProp
, obj
->getBaseType( ) == "cmis:folder" );
606 xRow
->appendBoolean( rProp
, false );
608 catch ( const libcmis::Exception
& )
610 if ( m_pObjectType
.get( ) )
611 xRow
->appendBoolean( rProp
, getObjectType( xEnv
)->getBaseType()->getId( ) == "cmis:folder" );
613 xRow
->appendVoid( rProp
);
616 else if ( rProp
.Name
== "Title" )
621 sTitle
= STD_TO_OUSTR( getObject( xEnv
)->getName() );
623 catch ( const libcmis::Exception
& )
625 if ( !m_pObjectProps
.empty() )
627 map
< string
, libcmis::PropertyPtr
>::iterator it
= m_pObjectProps
.find( "cmis:name" );
628 if ( it
!= m_pObjectProps
.end( ) )
630 vector
< string
> values
= it
->second
->getStrings( );
631 if ( !values
.empty() )
632 sTitle
= STD_TO_OUSTR( values
.front( ) );
637 // Nothing worked... get it from the path
638 if ( sTitle
.isEmpty( ) )
640 OUString sPath
= m_sObjectPath
;
642 // Get rid of the trailing slash problem
643 if ( sPath
.endsWith("/") )
644 sPath
= sPath
.copy( 0, sPath
.getLength() - 1 );
646 // Get the last segment
647 sal_Int32 nPos
= sPath
.lastIndexOf( '/' );
649 sTitle
= sPath
.copy( nPos
+ 1 );
652 if ( !sTitle
.isEmpty( ) )
653 xRow
->appendString( rProp
, sTitle
);
655 xRow
->appendVoid( rProp
);
657 else if ( rProp
.Name
== "ObjectId" )
662 sId
= STD_TO_OUSTR( getObject( xEnv
)->getId() );
664 catch ( const libcmis::Exception
& )
666 if ( !m_pObjectProps
.empty() )
668 map
< string
, libcmis::PropertyPtr
>::iterator it
= m_pObjectProps
.find( "cmis:objectId" );
669 if ( it
!= m_pObjectProps
.end( ) )
671 vector
< string
> values
= it
->second
->getStrings( );
672 if ( !values
.empty() )
673 sId
= STD_TO_OUSTR( values
.front( ) );
678 if ( !sId
.isEmpty( ) )
679 xRow
->appendString( rProp
, sId
);
681 xRow
->appendVoid( rProp
);
683 else if ( rProp
.Name
== "TitleOnServer" )
685 xRow
->appendString( rProp
, m_sObjectPath
);
687 else if ( rProp
.Name
== "IsReadOnly" )
689 boost::shared_ptr
< libcmis::AllowableActions
> allowableActions
= getObject( xEnv
)->getAllowableActions( );
690 bool bReadOnly
= false;
691 if ( !allowableActions
->isAllowed( libcmis::ObjectAction::SetContentStream
) &&
692 !allowableActions
->isAllowed( libcmis::ObjectAction::CheckIn
) )
695 xRow
->appendBoolean( rProp
, bReadOnly
);
697 else if ( rProp
.Name
== "DateCreated" )
699 util::DateTime aTime
= lcl_boostToUnoTime( getObject( xEnv
)->getCreationDate( ) );
700 xRow
->appendTimestamp( rProp
, aTime
);
702 else if ( rProp
.Name
== "DateModified" )
704 util::DateTime aTime
= lcl_boostToUnoTime( getObject( xEnv
)->getLastModificationDate( ) );
705 xRow
->appendTimestamp( rProp
, aTime
);
707 else if ( rProp
.Name
== "Size" )
711 libcmis::Document
* document
= dynamic_cast< libcmis::Document
* >( getObject( xEnv
).get( ) );
712 if ( NULL
!= document
)
713 xRow
->appendLong( rProp
, document
->getContentLength() );
715 xRow
->appendVoid( rProp
);
717 catch ( const libcmis::Exception
& )
719 xRow
->appendVoid( rProp
);
722 else if ( rProp
.Name
== "CreatableContentsInfo" )
724 xRow
->appendObject( rProp
, uno::makeAny( queryCreatableContentsInfo( xEnv
) ) );
726 else if ( rProp
.Name
== "MediaType" )
730 libcmis::Document
* document
= dynamic_cast< libcmis::Document
* >( getObject( xEnv
).get( ) );
731 if ( NULL
!= document
)
732 xRow
->appendString( rProp
, STD_TO_OUSTR( document
->getContentType() ) );
734 xRow
->appendVoid( rProp
);
736 catch ( const libcmis::Exception
& )
738 xRow
->appendVoid( rProp
);
741 else if ( rProp
.Name
== "IsVolume" )
743 xRow
->appendBoolean( rProp
, false );
745 else if ( rProp
.Name
== "IsRemote" )
747 xRow
->appendBoolean( rProp
, false );
749 else if ( rProp
.Name
== "IsRemoveable" )
751 xRow
->appendBoolean( rProp
, false );
753 else if ( rProp
.Name
== "IsFloppy" )
755 xRow
->appendBoolean( rProp
, false );
757 else if ( rProp
.Name
== "IsCompactDisc" )
759 xRow
->appendBoolean( rProp
, false );
761 else if ( rProp
.Name
== "IsHidden" )
763 xRow
->appendBoolean( rProp
, false );
765 else if ( rProp
.Name
== "TargetURL" )
767 xRow
->appendString( rProp
, "" );
769 else if ( rProp
.Name
== "BaseURI" )
771 xRow
->appendString( rProp
, m_aURL
.getBindingUrl( ) );
773 else if ( rProp
.Name
== "CmisProperties" )
777 libcmis::ObjectPtr object
= getObject( xEnv
);
778 map
< string
, libcmis::PropertyPtr
>& aProperties
= object
->getProperties( );
779 uno::Sequence
< document::CmisProperty
> aCmisProperties( aProperties
.size( ) );
780 document::CmisProperty
* pCmisProps
= aCmisProperties
.getArray( );
782 for ( map
< string
, libcmis::PropertyPtr
>::iterator it
= aProperties
.begin();
783 it
!= aProperties
.end( ); ++it
, ++i
)
785 string sId
= it
->first
;
786 string sDisplayName
= it
->second
->getPropertyType()->getDisplayName( );
787 bool bUpdatable
= it
->second
->getPropertyType()->isUpdatable( );
788 bool bRequired
= it
->second
->getPropertyType()->isRequired( );
789 bool bMultiValued
= it
->second
->getPropertyType()->isMultiValued();
790 bool bOpenChoice
= it
->second
->getPropertyType()->isOpenChoice();
792 pCmisProps
[i
].Id
= STD_TO_OUSTR( sId
);
793 pCmisProps
[i
].Name
= STD_TO_OUSTR( sDisplayName
);
794 pCmisProps
[i
].Updatable
= bUpdatable
;
795 pCmisProps
[i
].Required
= bRequired
;
796 pCmisProps
[i
].MultiValued
= bMultiValued
;
797 pCmisProps
[i
].OpenChoice
= bOpenChoice
;
798 pCmisProps
[i
].Value
= lcl_cmisPropertyToUno( it
->second
);
799 switch ( it
->second
->getPropertyType( )->getType( ) )
802 case libcmis::PropertyType::String
:
803 pCmisProps
[i
].Type
= CMIS_TYPE_STRING
;
805 case libcmis::PropertyType::Integer
:
806 pCmisProps
[i
].Type
= CMIS_TYPE_INTEGER
;
808 case libcmis::PropertyType::Decimal
:
809 pCmisProps
[i
].Type
= CMIS_TYPE_DECIMAL
;
811 case libcmis::PropertyType::Bool
:
812 pCmisProps
[i
].Type
= CMIS_TYPE_BOOL
;
814 case libcmis::PropertyType::DateTime
:
815 pCmisProps
[i
].Type
= CMIS_TYPE_DATETIME
;
820 xRow
->appendObject( rProp
.Name
, uno::makeAny( aCmisProperties
) );
822 catch ( const libcmis::Exception
& )
824 xRow
->appendVoid( rProp
);
827 else if ( rProp
.Name
== "IsVersionable" )
831 libcmis::ObjectPtr object
= getObject( xEnv
);
832 bool bIsVersionable
= object
->getTypeDescription( )->isVersionable( );
833 xRow
->appendBoolean( rProp
, bIsVersionable
);
835 catch ( const libcmis::Exception
& )
837 xRow
->appendVoid( rProp
);
840 else if ( rProp
.Name
== "CanCheckOut" )
844 libcmis::ObjectPtr pObject
= getObject( xEnv
);
845 libcmis::AllowableActionsPtr aAllowables
= pObject
->getAllowableActions( );
846 bool bAllowed
= false;
849 bAllowed
= aAllowables
->isAllowed( libcmis::ObjectAction::CheckOut
);
851 xRow
->appendBoolean( rProp
, bAllowed
);
853 catch ( const libcmis::Exception
& )
855 xRow
->appendVoid( rProp
);
858 else if ( rProp
.Name
== "CanCancelCheckOut" )
862 libcmis::ObjectPtr pObject
= getObject( xEnv
);
863 libcmis::AllowableActionsPtr aAllowables
= pObject
->getAllowableActions( );
864 bool bAllowed
= false;
867 bAllowed
= aAllowables
->isAllowed( libcmis::ObjectAction::CancelCheckOut
);
869 xRow
->appendBoolean( rProp
, bAllowed
);
871 catch ( const libcmis::Exception
& )
873 xRow
->appendVoid( rProp
);
876 else if ( rProp
.Name
== "CanCheckIn" )
880 libcmis::ObjectPtr pObject
= getObject( xEnv
);
881 libcmis::AllowableActionsPtr aAllowables
= pObject
->getAllowableActions( );
882 bool bAllowed
= false;
885 bAllowed
= aAllowables
->isAllowed( libcmis::ObjectAction::CheckIn
);
887 xRow
->appendBoolean( rProp
, bAllowed
);
889 catch ( const libcmis::Exception
& )
891 xRow
->appendVoid( rProp
);
895 SAL_INFO( "ucb.ucp.cmis", "Looking for unsupported property " << rProp
.Name
);
897 catch (const libcmis::Exception
&)
899 xRow
->appendVoid( rProp
);
903 return uno::Reference
< sdbc::XRow
>( xRow
.get() );
906 uno::Any
Content::open(const ucb::OpenCommandArgument2
& rOpenCommand
,
907 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
908 throw( uno::Exception
, libcmis::Exception
)
910 bool bIsFolder
= isFolder( xEnv
);
912 // Handle the case of the non-existing file
913 if ( !getObject( xEnv
) )
915 uno::Sequence
< uno::Any
> aArgs( 1 );
916 aArgs
[ 0 ] <<= m_xIdentifier
->getContentIdentifier();
917 uno::Any aErr
= uno::makeAny(
918 ucb::InteractiveAugmentedIOException(OUString(), static_cast< cppu::OWeakObject
* >( this ),
919 task::InteractionClassification_ERROR
,
920 bIsFolder
? ucb::IOErrorCode_NOT_EXISTING_PATH
: ucb::IOErrorCode_NOT_EXISTING
, aArgs
)
923 ucbhelper::cancelCommandExecution(aErr
, xEnv
);
929 ( rOpenCommand
.Mode
== ucb::OpenMode::ALL
) ||
930 ( rOpenCommand
.Mode
== ucb::OpenMode::FOLDERS
) ||
931 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENTS
)
934 if ( bOpenFolder
&& bIsFolder
)
936 uno::Reference
< ucb::XDynamicResultSet
> xSet
937 = new DynamicResultSet(m_xContext
, this, rOpenCommand
, xEnv
);
940 else if ( rOpenCommand
.Sink
.is() )
943 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
944 ( rOpenCommand
.Mode
== ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
)
947 ucbhelper::cancelCommandExecution(
948 uno::makeAny ( ucb::UnsupportedOpenModeException
949 ( OUString(), static_cast< cppu::OWeakObject
* >( this ),
950 sal_Int16( rOpenCommand
.Mode
) ) ),
954 if ( !feedSink( rOpenCommand
.Sink
, xEnv
) )
956 // Note: rOpenCommand.Sink may contain an XStream
957 // implementation. Support for this type of
958 // sink is optional...
959 SAL_INFO( "ucb.ucp.cmis", "Failed to copy data to sink" );
961 ucbhelper::cancelCommandExecution(
962 uno::makeAny (ucb::UnsupportedDataSinkException
963 ( OUString(), static_cast< cppu::OWeakObject
* >( this ),
964 rOpenCommand
.Sink
) ),
969 SAL_INFO( "ucb.ucp.cmis", "Open falling through ..." );
974 OUString
Content::checkIn( const ucb::CheckinArgument
& rArg
,
975 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
976 throw( uno::Exception
)
978 ucbhelper::Content
aSourceContent( rArg
.SourceURL
, xEnv
, comphelper::getProcessComponentContext( ) );
979 uno::Reference
< io::XInputStream
> xIn
= aSourceContent
.openStream( );
981 libcmis::ObjectPtr object
;
984 object
= getObject( xEnv
);
986 catch ( const libcmis::Exception
& )
990 libcmis::Document
* pPwc
= dynamic_cast< libcmis::Document
* >( object
.get( ) );
993 ucbhelper::cancelCommandExecution(
994 ucb::IOErrorCode_GENERAL
,
995 uno::Sequence
< uno::Any
>( 0 ),
997 "Checkin only supported by documents" );
1000 boost::shared_ptr
< ostream
> pOut( new ostringstream ( ios_base::binary
| ios_base::in
| ios_base::out
) );
1001 uno::Reference
< io::XOutputStream
> xOutput
= new ucbhelper::StdOutputStream( pOut
);
1002 copyData( xIn
, xOutput
);
1004 map
< string
, libcmis::PropertyPtr
> newProperties
;
1005 libcmis::DocumentPtr pDoc
= pPwc
->checkIn( rArg
.MajorVersion
, OUSTR_TO_STDSTR( rArg
.VersionComment
), newProperties
,
1006 pOut
, OUSTR_TO_STDSTR( rArg
.MimeType
), OUSTR_TO_STDSTR( rArg
.NewTitle
) );
1008 // Get the URL and send it back as a result
1009 URL
aCmisUrl( m_sURL
);
1010 vector
< string
> aPaths
= pDoc
->getPaths( );
1011 if ( !aPaths
.empty() )
1013 string sPath
= aPaths
.front( );
1014 aCmisUrl
.setObjectPath( STD_TO_OUSTR( sPath
) );
1018 // We may have unfiled document depending on the server, those
1019 // won't have any path, use their ID instead
1020 string sId
= pDoc
->getId( );
1021 aCmisUrl
.setObjectId( STD_TO_OUSTR( sId
) );
1023 return aCmisUrl
.asString( );
1026 OUString
Content::checkOut( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1027 throw( uno::Exception
)
1032 // Checkout the document if possible
1033 libcmis::DocumentPtr pDoc
= boost::dynamic_pointer_cast
< libcmis::Document
>( getObject( xEnv
) );
1034 if ( pDoc
.get( ) == NULL
)
1036 ucbhelper::cancelCommandExecution(
1037 ucb::IOErrorCode_GENERAL
,
1038 uno::Sequence
< uno::Any
>( 0 ),
1040 "Checkout only supported by documents" );
1042 libcmis::DocumentPtr pPwc
= pDoc
->checkOut( );
1044 // Compute the URL of the Private Working Copy (PWC)
1045 URL
aCmisUrl( m_sURL
);
1046 vector
< string
> aPaths
= pPwc
->getPaths( );
1047 if ( !aPaths
.empty() )
1049 string sPath
= aPaths
.front( );
1050 aCmisUrl
.setObjectPath( STD_TO_OUSTR( sPath
) );
1054 // We may have unfiled PWC depending on the server, those
1055 // won't have any path, use their ID instead
1056 string sId
= pPwc
->getId( );
1057 aCmisUrl
.setObjectId( STD_TO_OUSTR( sId
) );
1059 aRet
= aCmisUrl
.asString( );
1061 catch ( const libcmis::Exception
& e
)
1063 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1064 ucbhelper::cancelCommandExecution(
1065 ucb::IOErrorCode_GENERAL
,
1066 uno::Sequence
< uno::Any
>( 0 ),
1068 OUString::createFromAscii( e
.what() ) );
1073 OUString
Content::cancelCheckOut( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1074 throw( uno::Exception
)
1079 libcmis::DocumentPtr pPwc
= boost::dynamic_pointer_cast
< libcmis::Document
>( getObject( xEnv
) );
1080 if ( pPwc
.get( ) == NULL
)
1082 ucbhelper::cancelCommandExecution(
1083 ucb::IOErrorCode_GENERAL
,
1084 uno::Sequence
< uno::Any
>( 0 ),
1086 "CancelCheckout only supported by documents" );
1088 pPwc
->cancelCheckout( );
1090 // Get the Original document (latest version)
1091 vector
< libcmis::DocumentPtr
> aVersions
= pPwc
->getAllVersions( );
1092 bool bFound
= false;
1093 for ( vector
< libcmis::DocumentPtr
>::iterator it
= aVersions
.begin();
1094 it
!= aVersions
.end( ) && !bFound
; ++it
)
1096 libcmis::DocumentPtr pVersion
= *it
;
1097 map
< string
, libcmis::PropertyPtr
> aProps
= pVersion
->getProperties( );
1098 bool bIsLatestVersion
= false;
1099 map
< string
, libcmis::PropertyPtr
>::iterator propIt
= aProps
.find( string( "cmis:isLatestVersion" ) );
1100 if ( propIt
!= aProps
.end( ) && !propIt
->second
->getBools( ).empty( ) )
1102 bIsLatestVersion
= propIt
->second
->getBools( ).front( );
1105 if ( bIsLatestVersion
)
1108 // Compute the URL of the Document
1109 URL
aCmisUrl( m_sURL
);
1110 vector
< string
> aPaths
= pVersion
->getPaths( );
1111 if ( !aPaths
.empty() )
1113 string sPath
= aPaths
.front( );
1114 aCmisUrl
.setObjectPath( STD_TO_OUSTR( sPath
) );
1118 // We may have unfiled doc depending on the server, those
1119 // won't have any path, use their ID instead
1120 string sId
= pVersion
->getId( );
1121 aCmisUrl
.setObjectId( STD_TO_OUSTR( sId
) );
1123 aRet
= aCmisUrl
.asString( );
1127 catch ( const libcmis::Exception
& e
)
1129 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1130 ucbhelper::cancelCommandExecution(
1131 ucb::IOErrorCode_GENERAL
,
1132 uno::Sequence
< uno::Any
>( 0 ),
1134 OUString::createFromAscii( e
.what() ) );
1139 uno::Sequence
< document::CmisVersion
> Content::getAllVersions( const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1140 throw( uno::Exception
, std::exception
)
1145 libcmis::DocumentPtr pDoc
= boost::dynamic_pointer_cast
< libcmis::Document
>( getObject( xEnv
) );
1146 if ( pDoc
.get( ) == NULL
)
1148 ucbhelper::cancelCommandExecution(
1149 ucb::IOErrorCode_GENERAL
,
1150 uno::Sequence
< uno::Any
>( 0 ),
1152 "Can not get the document" );
1154 vector
< libcmis::DocumentPtr
> aCmisVersions
= pDoc
->getAllVersions( );
1155 uno::Sequence
< document::CmisVersion
> aVersions( aCmisVersions
.size( ) );
1157 for ( vector
< libcmis::DocumentPtr
>::iterator it
= aCmisVersions
.begin();
1158 it
!= aCmisVersions
.end( ); ++it
, ++i
)
1160 libcmis::DocumentPtr pVersion
= *it
;
1161 aVersions
[i
].Id
= STD_TO_OUSTR( pVersion
->getId( ) );
1162 aVersions
[i
].Author
= STD_TO_OUSTR( pVersion
->getCreatedBy( ) );
1163 aVersions
[i
].TimeStamp
= lcl_boostToUnoTime( pVersion
->getLastModificationDate( ) );
1164 aVersions
[i
].Comment
= STD_TO_OUSTR( pVersion
->getStringProperty("cmis:checkinComment") );
1168 catch ( const libcmis::Exception
& e
)
1170 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1171 ucbhelper::cancelCommandExecution(
1172 ucb::IOErrorCode_GENERAL
,
1173 uno::Sequence
< uno::Any
>( 0 ),
1175 OUString::createFromAscii( e
.what() ) );
1177 return uno::Sequence
< document::CmisVersion
> ( );
1180 void Content::transfer( const ucb::TransferInfo
& rTransferInfo
,
1181 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1182 throw( uno::Exception
)
1184 // If the source isn't on the same CMIS repository, then simply copy
1185 INetURLObject
aSourceUrl( rTransferInfo
.SourceURL
);
1186 if ( aSourceUrl
.GetProtocol() != INetProtocol::Cmis
)
1188 OUString sSrcBindingUrl
= URL( rTransferInfo
.SourceURL
).getBindingUrl( );
1189 if ( sSrcBindingUrl
!= m_aURL
.getBindingUrl( ) )
1191 ucbhelper::cancelCommandExecution(
1193 ucb::InteractiveBadTransferURLException(
1194 OUString("Unsupported URL scheme!"),
1195 static_cast< cppu::OWeakObject
* >( this ) ) ),
1200 SAL_INFO( "ucb.ucp.cmis", "TODO - Content::transfer()" );
1203 void Content::insert( const uno::Reference
< io::XInputStream
> & xInputStream
,
1204 bool bReplaceExisting
, const OUString
& rMimeType
,
1205 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1206 throw (uno::Exception
, std::exception
)
1208 if ( !xInputStream
.is() )
1210 ucbhelper::cancelCommandExecution( uno::makeAny
1211 ( ucb::MissingInputStreamException
1212 ( OUString(), static_cast< cppu::OWeakObject
* >( this ) ) ),
1216 // For transient content, the URL is the one of the parent
1221 // Try to get the object from the server if there is any
1222 libcmis::FolderPtr pFolder
;
1225 pFolder
= boost::dynamic_pointer_cast
< libcmis::Folder
>( getObject( xEnv
) );
1227 catch ( const libcmis::Exception
& )
1233 libcmis::ObjectPtr object
;
1234 map
< string
, libcmis::PropertyPtr
>::iterator it
= m_pObjectProps
.find( "cmis:name" );
1235 if ( it
== m_pObjectProps
.end( ) )
1237 ucbhelper::cancelCommandExecution( uno::makeAny
1238 ( uno::RuntimeException( "Missing name property",
1239 static_cast< cppu::OWeakObject
* >( this ) ) ),
1242 string newName
= it
->second
->getStrings( ).front( );
1243 string newPath
= OUSTR_TO_STDSTR( m_sObjectPath
);
1244 if ( !newPath
.empty( ) && newPath
[ newPath
.size( ) - 1 ] != '/' )
1249 if ( !m_sObjectId
.isEmpty( ) )
1250 object
= getSession( xEnv
)->getObject( OUSTR_TO_STDSTR( m_sObjectId
) );
1252 object
= getSession( xEnv
)->getObjectByPath( newPath
);
1253 sNewPath
= STD_TO_OUSTR( newPath
);
1255 catch ( const libcmis::Exception
& )
1257 // Nothing matched the path
1260 if ( NULL
!= object
.get( ) )
1262 // Are the base type matching?
1263 if ( object
->getBaseType( ) != m_pObjectType
->getBaseType( )->getId() )
1265 ucbhelper::cancelCommandExecution( uno::makeAny
1266 ( uno::RuntimeException( "Can't change a folder into a document and vice-versa.",
1267 static_cast< cppu::OWeakObject
* >( this ) ) ),
1271 // Update the existing object if it's a document
1272 libcmis::Document
* document
= dynamic_cast< libcmis::Document
* >( object
.get( ) );
1273 if ( NULL
!= document
)
1275 boost::shared_ptr
< ostream
> pOut( new ostringstream ( ios_base::binary
| ios_base::in
| ios_base::out
) );
1276 uno::Reference
< io::XOutputStream
> xOutput
= new ucbhelper::StdOutputStream( pOut
);
1277 copyData( xInputStream
, xOutput
);
1280 document
->setContentStream( pOut
, OUSTR_TO_STDSTR( rMimeType
), string( ), bReplaceExisting
);
1282 catch ( const libcmis::Exception
& )
1284 ucbhelper::cancelCommandExecution( uno::makeAny
1285 ( uno::RuntimeException( "Error when setting document content",
1286 static_cast< cppu::OWeakObject
* >( this ) ) ),
1293 // We need to create a brand new object... either folder or document
1294 bool bIsFolder
= getObjectType( xEnv
)->getBaseType( )->getId( ) == "cmis:folder";
1295 setCmisProperty( "cmis:objectTypeId", getObjectType( xEnv
)->getId( ), xEnv
);
1301 libcmis::FolderPtr pNew
= pFolder
->createFolder( m_pObjectProps
);
1302 sNewPath
= STD_TO_OUSTR( newPath
);
1304 catch ( const libcmis::Exception
& )
1306 ucbhelper::cancelCommandExecution( uno::makeAny
1307 ( uno::RuntimeException( "Error when creating folder",
1308 static_cast< cppu::OWeakObject
* >( this ) ) ),
1314 boost::shared_ptr
< ostream
> pOut( new ostringstream ( ios_base::binary
| ios_base::in
| ios_base::out
) );
1315 uno::Reference
< io::XOutputStream
> xOutput
= new ucbhelper::StdOutputStream( pOut
);
1316 copyData( xInputStream
, xOutput
);
1319 pFolder
->createDocument( m_pObjectProps
, pOut
, OUSTR_TO_STDSTR( rMimeType
), string() );
1320 sNewPath
= STD_TO_OUSTR( newPath
);
1322 catch ( const libcmis::Exception
& )
1324 ucbhelper::cancelCommandExecution( uno::makeAny
1325 ( uno::RuntimeException( "Error when creating document",
1326 static_cast< cppu::OWeakObject
* >( this ) ) ),
1332 if ( !sNewPath
.isEmpty( ) || !m_sObjectId
.isEmpty( ) )
1334 // Update the current content: it's no longer transient
1335 m_sObjectPath
= sNewPath
;
1337 aUrl
.setObjectPath( m_sObjectPath
);
1338 aUrl
.setObjectId( m_sObjectId
);
1339 m_sURL
= aUrl
.asString( );
1341 m_pObjectType
.reset( );
1342 m_pObjectProps
.clear( );
1343 m_bTransient
= false;
1350 const int TRANSFER_BUFFER_SIZE
= 65536;
1352 void Content::copyData(
1353 uno::Reference
< io::XInputStream
> xIn
,
1354 uno::Reference
< io::XOutputStream
> xOut
)
1356 uno::Sequence
< sal_Int8
> theData( TRANSFER_BUFFER_SIZE
);
1358 while ( xIn
->readBytes( theData
, TRANSFER_BUFFER_SIZE
) > 0 )
1359 xOut
->writeBytes( theData
);
1361 xOut
->closeOutput();
1364 uno::Sequence
< uno::Any
> Content::setPropertyValues(
1365 const uno::Sequence
< beans::PropertyValue
>& rValues
,
1366 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1370 // Get the already set properties if possible
1371 if ( !m_bTransient
&& getObject( xEnv
).get( ) )
1373 m_pObjectProps
.clear( );
1374 m_pObjectType
= getObject( xEnv
)->getTypeDescription();
1377 catch ( const libcmis::Exception
& e
)
1379 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1380 ucbhelper::cancelCommandExecution(
1381 ucb::IOErrorCode_GENERAL
,
1382 uno::Sequence
< uno::Any
>( 0 ),
1384 OUString::createFromAscii( e
.what() ) );
1387 sal_Int32 nCount
= rValues
.getLength();
1388 uno::Sequence
< uno::Any
> aRet( nCount
);
1390 bool bChanged
= false;
1391 const beans::PropertyValue
* pValues
= rValues
.getConstArray();
1392 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
1394 const beans::PropertyValue
& rValue
= pValues
[ n
];
1395 if ( rValue
.Name
== "ContentType" ||
1396 rValue
.Name
== "MediaType" ||
1397 rValue
.Name
== "IsDocument" ||
1398 rValue
.Name
== "IsFolder" ||
1399 rValue
.Name
== "Size" ||
1400 rValue
.Name
== "CreatableContentsInfo" )
1402 lang::IllegalAccessException
e ( OUString("Property is read-only!"),
1403 static_cast< cppu::OWeakObject
* >( this ) );
1406 else if ( rValue
.Name
== "Title" )
1409 if (!( rValue
.Value
>>= aNewTitle
))
1411 aRet
[ n
] <<= beans::IllegalTypeException
1412 ( OUString("Property value has wrong type!"),
1413 static_cast< cppu::OWeakObject
* >( this ) );
1417 if ( aNewTitle
.getLength() <= 0 )
1419 aRet
[ n
] <<= lang::IllegalArgumentException
1420 ( OUString("Empty title not allowed!"),
1421 static_cast< cppu::OWeakObject
* >( this ), -1 );
1426 setCmisProperty( "cmis:name", OUSTR_TO_STDSTR( aNewTitle
), xEnv
);
1431 SAL_INFO( "ucb.ucp.cmis", "Couln't set property: " << rValue
.Name
);
1432 lang::IllegalAccessException
e ( OUString("Property is read-only!"),
1433 static_cast< cppu::OWeakObject
* >( this ) );
1440 if ( !m_bTransient
&& bChanged
)
1442 getObject( xEnv
)->updateProperties( m_pObjectProps
);
1445 catch ( const libcmis::Exception
& e
)
1447 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1448 ucbhelper::cancelCommandExecution(
1449 ucb::IOErrorCode_GENERAL
,
1450 uno::Sequence
< uno::Any
>( 0 ),
1452 OUString::createFromAscii( e
.what() ) );
1458 bool Content::feedSink( uno::Reference
< uno::XInterface
> xSink
,
1459 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1464 uno::Reference
< io::XOutputStream
> xOut
= uno::Reference
< io::XOutputStream
>(xSink
, uno::UNO_QUERY
);
1465 uno::Reference
< io::XActiveDataSink
> xDataSink
= uno::Reference
< io::XActiveDataSink
>(xSink
, uno::UNO_QUERY
);
1466 uno::Reference
< io::XActiveDataStreamer
> xDataStreamer
= uno::Reference
< io::XActiveDataStreamer
>( xSink
, uno::UNO_QUERY
);
1468 if ( !xOut
.is() && !xDataSink
.is() && ( !xDataStreamer
.is() || !xDataStreamer
->getStream().is() ) )
1471 if ( xDataStreamer
.is() && !xOut
.is() )
1472 xOut
= xDataStreamer
->getStream()->getOutputStream();
1476 libcmis::Document
* document
= dynamic_cast< libcmis::Document
* >( getObject( xEnv
).get() );
1481 boost::shared_ptr
< istream
> aIn
= document
->getContentStream( );
1483 uno::Reference
< io::XInputStream
> xIn
= new ucbhelper::StdInputStream( aIn
);
1487 if ( xDataSink
.is() )
1488 xDataSink
->setInputStream( xIn
);
1489 else if ( xOut
.is() )
1490 copyData( xIn
, xOut
);
1492 catch ( const libcmis::Exception
& e
)
1494 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1495 ucbhelper::cancelCommandExecution(
1496 ucb::IOErrorCode_GENERAL
,
1497 uno::Sequence
< uno::Any
>( 0 ),
1499 OUString::createFromAscii( e
.what() ) );
1505 uno::Sequence
< beans::Property
> Content::getProperties(
1506 const uno::Reference
< ucb::XCommandEnvironment
> & )
1508 static const beans::Property aGenericProperties
[] =
1510 beans::Property( OUString( "IsDocument" ),
1511 -1, cppu::UnoType
<bool>::get(),
1512 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1513 beans::Property( OUString( "IsFolder" ),
1514 -1, cppu::UnoType
<bool>::get(),
1515 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1516 beans::Property( OUString( "Title" ),
1517 -1, cppu::UnoType
<OUString
>::get(),
1518 beans::PropertyAttribute::BOUND
),
1519 beans::Property( OUString( "ObjectId" ),
1520 -1, cppu::UnoType
<OUString
>::get(),
1521 beans::PropertyAttribute::BOUND
),
1522 beans::Property( OUString( "TitleOnServer" ),
1523 -1, cppu::UnoType
<OUString
>::get(),
1524 beans::PropertyAttribute::BOUND
),
1525 beans::Property( OUString( "IsReadOnly" ),
1526 -1, cppu::UnoType
<bool>::get(),
1527 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1528 beans::Property( OUString( "DateCreated" ),
1529 -1, cppu::UnoType
<util::DateTime
>::get(),
1530 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1531 beans::Property( OUString( "DateModified" ),
1532 -1, cppu::UnoType
<util::DateTime
>::get(),
1533 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1534 beans::Property( OUString( "Size" ),
1535 -1, cppu::UnoType
<sal_Int64
>::get(),
1536 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1537 beans::Property( OUString( "CreatableContentsInfo" ),
1538 -1, cppu::UnoType
<uno::Sequence
< ucb::ContentInfo
>>::get(),
1539 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1540 beans::Property( OUString( "MediaType" ),
1541 -1, cppu::UnoType
<OUString
>::get(),
1542 beans::PropertyAttribute::BOUND
),
1543 beans::Property( OUString( "CmisProperties" ),
1544 -1, cppu::UnoType
<uno::Sequence
< document::CmisProperty
>>::get(),
1545 beans::PropertyAttribute::BOUND
),
1546 beans::Property( OUString( "IsVersionable" ),
1547 -1, cppu::UnoType
<bool>::get(),
1548 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1549 beans::Property( OUString( "CanCheckOut" ),
1550 -1, cppu::UnoType
<bool>::get(),
1551 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1552 beans::Property( OUString( "CanCancelCheckOut" ),
1553 -1, cppu::UnoType
<bool>::get(),
1554 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1555 beans::Property( OUString( "CanCheckIn" ),
1556 -1, cppu::UnoType
<bool>::get(),
1557 beans::PropertyAttribute::BOUND
| beans::PropertyAttribute::READONLY
),
1560 const int nProps
= SAL_N_ELEMENTS(aGenericProperties
);
1561 return uno::Sequence
< beans::Property
> ( aGenericProperties
, nProps
);
1564 uno::Sequence
< ucb::CommandInfo
> Content::getCommands(
1565 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1567 static const ucb::CommandInfo aCommandInfoTable
[] =
1569 // Required commands
1571 ( OUString( "getCommandInfo" ),
1572 -1, cppu::UnoType
<void>::get() ),
1574 ( OUString( "getPropertySetInfo" ),
1575 -1, cppu::UnoType
<void>::get() ),
1577 ( OUString( "getPropertyValues" ),
1578 -1, cppu::UnoType
<uno::Sequence
< beans::Property
>>::get() ),
1580 ( OUString( "setPropertyValues" ),
1581 -1, cppu::UnoType
<uno::Sequence
< beans::PropertyValue
>>::get() ),
1583 // Optional standard commands
1585 ( OUString( "delete" ),
1586 -1, cppu::UnoType
<bool>::get() ),
1588 ( OUString( "insert" ),
1589 -1, cppu::UnoType
<ucb::InsertCommandArgument2
>::get() ),
1591 ( OUString( "open" ),
1592 -1, cppu::UnoType
<ucb::OpenCommandArgument2
>::get() ),
1594 // Mandatory CMIS-only commands
1595 ucb::CommandInfo ( OUString( "checkout" ), -1, cppu::UnoType
<void>::get() ),
1596 ucb::CommandInfo ( OUString( "cancelCheckout" ), -1, cppu::UnoType
<void>::get() ),
1597 ucb::CommandInfo ( OUString( "checkIn" ), -1,
1598 cppu::UnoType
<ucb::TransferInfo
>::get() ),
1599 ucb::CommandInfo ( OUString( "updateProperties" ), -1, cppu::UnoType
<void>::get() ),
1601 ( OUString( "getAllVersions" ),
1602 -1, cppu::UnoType
<uno::Sequence
< document::CmisVersion
>>::get() ),
1605 // Folder Only, omitted if not a folder
1607 ( OUString( "transfer" ),
1608 -1, cppu::UnoType
<ucb::TransferInfo
>::get() ),
1610 ( OUString( "createNewContent" ),
1611 -1, cppu::UnoType
<ucb::ContentInfo
>::get() )
1614 const int nProps
= SAL_N_ELEMENTS( aCommandInfoTable
);
1615 return uno::Sequence
< ucb::CommandInfo
>(aCommandInfoTable
, isFolder( xEnv
) ? nProps
: nProps
- 2);
1618 OUString
Content::getParentURL( )
1620 SAL_INFO( "ucb.ucp.cmis", "Content::getParentURL()" );
1621 OUString parentUrl
= "/";
1622 if ( m_sObjectPath
== "/" )
1626 INetURLObject
aUrl( m_sURL
);
1627 if ( aUrl
.getSegmentCount( ) > 0 )
1629 URL
aCmisUrl( m_sURL
);
1630 aUrl
.removeSegment( );
1631 aCmisUrl
.setObjectPath( aUrl
.GetURLPath( INetURLObject::DECODE_WITH_CHARSET
) );
1632 parentUrl
= aCmisUrl
.asString( );
1638 XTYPEPROVIDER_COMMON_IMPL( Content
);
1640 void SAL_CALL
Content::acquire() throw()
1642 ContentImplHelper::acquire();
1645 void SAL_CALL
Content::release() throw()
1647 ContentImplHelper::release();
1650 uno::Any SAL_CALL
Content::queryInterface( const uno::Type
& rType
) throw ( uno::RuntimeException
, std::exception
)
1652 uno::Any aRet
= cppu::queryInterface( rType
, static_cast< ucb::XContentCreator
* >( this ) );
1653 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface(rType
);
1656 OUString SAL_CALL
Content::getImplementationName() throw( uno::RuntimeException
, std::exception
)
1658 return OUString("com.sun.star.comp.CmisContent");
1661 uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
1662 throw( uno::RuntimeException
, std::exception
)
1664 uno::Sequence
< OUString
> aSNS( 1 );
1665 aSNS
.getArray()[ 0 ] = "com.sun.star.ucb.CmisContent";
1669 OUString SAL_CALL
Content::getContentType() throw( uno::RuntimeException
, std::exception
)
1674 sRet
= isFolder( uno::Reference
< ucb::XCommandEnvironment
>() )
1675 ? OUString(CMIS_FOLDER_TYPE
)
1676 : OUString(CMIS_FILE_TYPE
);
1678 catch (const uno::RuntimeException
&)
1682 catch (const uno::Exception
& e
)
1684 uno::Any
a(cppu::getCaughtException());
1685 throw lang::WrappedTargetRuntimeException(
1686 "wrapped Exception " + e
.Message
,
1687 uno::Reference
<uno::XInterface
>(), a
);
1692 uno::Any SAL_CALL
Content::execute(
1693 const ucb::Command
& aCommand
,
1694 sal_Int32
/*CommandId*/,
1695 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1696 throw( uno::Exception
, ucb::CommandAbortedException
, uno::RuntimeException
, std::exception
)
1698 SAL_INFO( "ucb.ucp.cmis", "Content::execute( ) - " << aCommand
.Name
);
1701 if ( aCommand
.Name
== "getPropertyValues" )
1703 uno::Sequence
< beans::Property
> Properties
;
1704 if ( !( aCommand
.Argument
>>= Properties
) )
1705 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1706 aRet
<<= getPropertyValues( Properties
, xEnv
);
1708 else if ( aCommand
.Name
== "getPropertySetInfo" )
1709 aRet
<<= getPropertySetInfo( xEnv
, false );
1710 else if ( aCommand
.Name
== "getCommandInfo" )
1711 aRet
<<= getCommandInfo( xEnv
, false );
1712 else if ( aCommand
.Name
== "open" )
1714 ucb::OpenCommandArgument2 aOpenCommand
;
1715 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
1716 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1717 aRet
= open( aOpenCommand
, xEnv
);
1719 else if ( aCommand
.Name
== "transfer" )
1721 ucb::TransferInfo transferArgs
;
1722 if ( !( aCommand
.Argument
>>= transferArgs
) )
1723 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1724 transfer( transferArgs
, xEnv
);
1726 else if ( aCommand
.Name
== "setPropertyValues" )
1728 uno::Sequence
< beans::PropertyValue
> aProperties
;
1729 if ( !( aCommand
.Argument
>>= aProperties
) || !aProperties
.getLength() )
1730 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1731 aRet
<<= setPropertyValues( aProperties
, xEnv
);
1733 else if (aCommand
.Name
== "createNewContent"
1734 && isFolder( xEnv
) )
1736 ucb::ContentInfo arg
;
1737 if ( !( aCommand
.Argument
>>= arg
) )
1738 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1739 aRet
<<= createNewContent( arg
);
1741 else if ( aCommand
.Name
== "insert" )
1743 ucb::InsertCommandArgument2 arg
;
1744 if ( !( aCommand
.Argument
>>= arg
) )
1746 ucb::InsertCommandArgument insertArg
;
1747 if ( !( aCommand
.Argument
>>= insertArg
) )
1748 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
1750 arg
.Data
= insertArg
.Data
;
1751 arg
.ReplaceExisting
= insertArg
.ReplaceExisting
;
1753 // store the document id
1754 m_sObjectId
= arg
.DocumentId
;
1755 insert( arg
.Data
, arg
.ReplaceExisting
, arg
.MimeType
, xEnv
);
1757 else if ( aCommand
.Name
== "delete" )
1761 if ( !isFolder( xEnv
) )
1763 getObject( xEnv
)->remove( );
1767 libcmis::Folder
* folder
= dynamic_cast< libcmis::Folder
* >( getObject( xEnv
).get() );
1769 folder
->removeTree( );
1772 catch ( const libcmis::Exception
& e
)
1774 SAL_INFO( "ucb.ucp.cmis", "Unexpected libcmis exception: " << e
.what( ) );
1775 ucbhelper::cancelCommandExecution(
1776 ucb::IOErrorCode_GENERAL
,
1777 uno::Sequence
< uno::Any
>( 0 ),
1779 OUString::createFromAscii( e
.what() ) );
1782 else if ( aCommand
.Name
== "checkout" )
1784 aRet
<<= checkOut( xEnv
);
1786 else if ( aCommand
.Name
== "cancelCheckout" )
1788 aRet
<<= cancelCheckOut( xEnv
);
1790 else if ( aCommand
.Name
== "checkin" )
1792 ucb::CheckinArgument aArg
;
1793 if ( !( aCommand
.Argument
>>= aArg
) )
1795 ucbhelper::cancelCommandExecution ( getBadArgExcept(), xEnv
);
1797 aRet
<<= checkIn( aArg
, xEnv
);
1799 else if ( aCommand
.Name
== "getAllVersions" )
1801 aRet
<<= getAllVersions( xEnv
);
1803 else if ( aCommand
.Name
== "updateProperties" )
1805 updateProperties( aCommand
.Argument
, xEnv
);
1809 SAL_INFO( "ucb.ucp.cmis", "Unknown command to execute" );
1811 ucbhelper::cancelCommandExecution
1812 ( uno::makeAny( ucb::UnsupportedCommandException
1814 static_cast< cppu::OWeakObject
* >( this ) ) ),
1821 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ ) throw( uno::RuntimeException
, std::exception
)
1823 SAL_INFO( "ucb.ucp.cmis", "TODO - Content::abort()" );
1824 // TODO Implement me
1827 uno::Sequence
< ucb::ContentInfo
> SAL_CALL
Content::queryCreatableContentsInfo()
1828 throw( uno::RuntimeException
, std::exception
)
1830 return queryCreatableContentsInfo( uno::Reference
< ucb::XCommandEnvironment
>() );
1833 uno::Reference
< ucb::XContent
> SAL_CALL
Content::createNewContent(
1834 const ucb::ContentInfo
& Info
) throw( uno::RuntimeException
, std::exception
)
1836 bool create_document
;
1838 if ( Info
.Type
== CMIS_FILE_TYPE
)
1839 create_document
= true;
1840 else if ( Info
.Type
== CMIS_FOLDER_TYPE
)
1841 create_document
= false;
1844 SAL_INFO( "ucb.ucp.cmis", "Unknown type of content to create" );
1845 return uno::Reference
< ucb::XContent
>();
1848 OUString sParentURL
= m_xIdentifier
->getContentIdentifier();
1849 URL
aParentURL( sParentURL
);
1851 // Set the parent URL for the transient objects
1852 uno::Reference
< ucb::XContentIdentifier
> xId(new ::ucbhelper::ContentIdentifier(sParentURL
));
1856 return new ::cmis::Content( m_xContext
, m_pProvider
, xId
, !create_document
);
1858 catch ( ucb::ContentCreationException
& )
1860 return uno::Reference
< ucb::XContent
>();
1864 uno::Sequence
< uno::Type
> SAL_CALL
Content::getTypes() throw( uno::RuntimeException
, std::exception
)
1868 if ( isFolder( uno::Reference
< ucb::XCommandEnvironment
>() ) )
1870 static cppu::OTypeCollection aFolderCollection
1871 (CPPU_TYPE_REF( lang::XTypeProvider
),
1872 CPPU_TYPE_REF( lang::XServiceInfo
),
1873 CPPU_TYPE_REF( lang::XComponent
),
1874 CPPU_TYPE_REF( ucb::XContent
),
1875 CPPU_TYPE_REF( ucb::XCommandProcessor
),
1876 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
1877 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
1878 CPPU_TYPE_REF( beans::XPropertyContainer
),
1879 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
1880 CPPU_TYPE_REF( container::XChild
),
1881 CPPU_TYPE_REF( ucb::XContentCreator
) );
1882 return aFolderCollection
.getTypes();
1885 catch (const uno::RuntimeException
&)
1889 catch (const uno::Exception
& e
)
1891 uno::Any
a(cppu::getCaughtException());
1892 throw lang::WrappedTargetRuntimeException(
1893 "wrapped Exception " + e
.Message
,
1894 uno::Reference
<uno::XInterface
>(), a
);
1897 static cppu::OTypeCollection aFileCollection
1898 (CPPU_TYPE_REF( lang::XTypeProvider
),
1899 CPPU_TYPE_REF( lang::XServiceInfo
),
1900 CPPU_TYPE_REF( lang::XComponent
),
1901 CPPU_TYPE_REF( ucb::XContent
),
1902 CPPU_TYPE_REF( ucb::XCommandProcessor
),
1903 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier
),
1904 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier
),
1905 CPPU_TYPE_REF( beans::XPropertyContainer
),
1906 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier
),
1907 CPPU_TYPE_REF( container::XChild
) );
1909 return aFileCollection
.getTypes();
1912 uno::Sequence
< ucb::ContentInfo
> Content::queryCreatableContentsInfo(
1913 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
1914 throw( uno::RuntimeException
)
1918 if ( isFolder( xEnv
) )
1920 uno::Sequence
< ucb::ContentInfo
> seq(2);
1922 // Minimum set of props we really need
1923 uno::Sequence
< beans::Property
> props( 1 );
1924 props
[0] = beans::Property(
1927 cppu::UnoType
<OUString
>::get(),
1928 beans::PropertyAttribute::MAYBEVOID
| beans::PropertyAttribute::BOUND
);
1931 seq
[0].Type
= CMIS_FILE_TYPE
;
1932 seq
[0].Attributes
= ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
|
1933 ucb::ContentInfoAttribute::KIND_DOCUMENT
);
1934 seq
[0].Properties
= props
;
1937 seq
[1].Type
= CMIS_FOLDER_TYPE
;
1938 seq
[1].Attributes
= ucb::ContentInfoAttribute::KIND_FOLDER
;
1939 seq
[1].Properties
= props
;
1944 catch (const uno::RuntimeException
&)
1948 catch (const uno::Exception
& e
)
1950 uno::Any
a(cppu::getCaughtException());
1951 throw lang::WrappedTargetRuntimeException(
1952 "wrapped Exception " + e
.Message
,
1953 uno::Reference
<uno::XInterface
>(), a
);
1955 return uno::Sequence
< ucb::ContentInfo
>();
1958 list
< uno::Reference
< ucb::XContent
> > Content::getChildren( )
1960 list
< uno::Reference
< ucb::XContent
> > results
;
1961 SAL_INFO( "ucb.ucp.cmis", "Content::getChildren() " << m_sURL
);
1963 libcmis::FolderPtr pFolder
= boost::dynamic_pointer_cast
< libcmis::Folder
>( getObject( uno::Reference
< ucb::XCommandEnvironment
>() ) );
1966 // Get the children from pObject
1969 vector
< libcmis::ObjectPtr
> children
= pFolder
->getChildren( );
1971 // Loop over the results
1972 for ( vector
< libcmis::ObjectPtr
>::iterator it
= children
.begin();
1973 it
!= children
.end(); ++it
)
1975 // TODO Cache the objects
1978 OUString
sPath( m_sObjectPath
);
1979 if ( !sPath
.endsWith("/") )
1981 sPath
+= STD_TO_OUSTR( ( *it
)->getName( ) );
1982 OUString sId
= STD_TO_OUSTR( ( *it
)->getId( ) );
1983 aUrl
.setObjectId( sId
);
1984 aUrl
.setObjectPath( sPath
);
1985 uno::Reference
< ucb::XContentIdentifier
> xId
= new ucbhelper::ContentIdentifier( aUrl
.asString( ) );
1986 uno::Reference
< ucb::XContent
> xContent
= new Content( m_xContext
, m_pProvider
, xId
, *it
);
1988 results
.push_back( xContent
);
1991 catch ( const libcmis::Exception
& e
)
1993 SAL_INFO( "ucb.ucp.cmis", "Exception thrown: " << e
.what() );
2000 void Content::setCmisProperty(const std::string
& rName
, const std::string
& rValue
, const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
)
2002 if ( getObjectType( xEnv
).get( ) )
2004 map
< string
, libcmis::PropertyPtr
>::iterator propIt
= m_pObjectProps
.find(rName
);
2005 vector
< string
> values
;
2006 values
.push_back(rValue
);
2008 if ( propIt
== m_pObjectProps
.end( ) && getObjectType( xEnv
).get( ) )
2010 map
< string
, libcmis::PropertyTypePtr
> propsTypes
= getObjectType( xEnv
)->getPropertiesTypes( );
2011 map
< string
, libcmis::PropertyTypePtr
>::iterator typeIt
= propsTypes
.find(rName
);
2013 if ( typeIt
!= propsTypes
.end( ) )
2015 libcmis::PropertyTypePtr propType
= typeIt
->second
;
2016 libcmis::PropertyPtr
property( new libcmis::Property( propType
, values
) );
2017 m_pObjectProps
.insert(pair
< string
, libcmis::PropertyPtr
>(rName
, property
));
2020 else if ( propIt
!= m_pObjectProps
.end( ) )
2022 propIt
->second
->setValues( values
);
2028 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */