fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / ucb / source / ucp / cmis / cmis_content.cxx
blob34f5b9f8018b3f9c657ce935cd1d6e9bd02158cb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include <cstdio>
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>
36 #ifndef SYSTEM_CURL
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>
41 #endif
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;
66 using namespace std;
68 namespace
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;
88 return unoTime;
91 uno::Any lcl_cmisPropertyToUno( libcmis::PropertyPtr pProperty )
93 uno::Any aValue;
94 switch ( pProperty->getPropertyType( )->getType( ) )
96 default:
97 case libcmis::PropertyType::String:
99 vector< string > aCmisStrings = pProperty->getStrings( );
100 uno::Sequence< OUString > aStrings( aCmisStrings.size( ) );
101 OUString* aStringsArr = aStrings.getArray( );
102 sal_Int32 i = 0;
103 for ( vector< string >::iterator it = aCmisStrings.begin( );
104 it != aCmisStrings.end( ); ++it, ++i )
106 string str = *it;
107 aStringsArr[i] = STD_TO_OUSTR( str );
109 aValue <<= aStrings;
111 break;
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( );
117 sal_Int32 i = 0;
118 for ( vector< long >::iterator it = aCmisLongs.begin( );
119 it != aCmisLongs.end( ); ++it, ++i )
121 aLongsArr[i] = *it;
123 aValue <<= aLongs;
125 break;
126 case libcmis::PropertyType::Decimal:
128 vector< double > aCmisDoubles = pProperty->getDoubles( );
129 uno::Sequence< double > aDoubles( aCmisDoubles.size( ) );
130 double* aDoublesArr = aDoubles.getArray( );
131 sal_Int32 i = 0;
132 for ( vector< double >::iterator it = aCmisDoubles.begin( );
133 it != aCmisDoubles.end( ); ++it, ++i )
135 aDoublesArr[i] = *it;
137 aValue <<= aDoubles;
139 break;
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( );
145 sal_Int32 i = 0;
146 for ( vector< bool >::iterator it = aCmisBools.begin( );
147 it != aCmisBools.end( ); ++it, ++i )
149 aBoolsArr[i] = *it;
151 aValue <<= aBools;
153 break;
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( );
159 sal_Int32 i = 0;
160 for ( vector< boost::posix_time::ptime >::iterator it = aCmisTimes.begin( );
161 it != aCmisTimes.end( ); ++it, ++i )
163 aTimesArr[i] = lcl_boostToUnoTime( *it );
165 aValue <<= aTimes;
167 break;
169 return aValue;
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;
189 value >>= 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;
200 value >>= 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;
211 value >>= 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;
222 value >>= 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;
233 value >>= 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 ) );
254 return property;
258 namespace cmis
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 ),
266 m_pSession( NULL ),
267 m_pObject( pObject ),
268 m_sURL( Identifier->getContentIdentifier( ) ),
269 m_aURL( Identifier->getContentIdentifier( ) ),
270 m_bTransient( false ),
271 m_bIsFolder( 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,
281 bool bIsFolder )
282 throw ( ucb::ContentCreationException )
283 : ContentImplHelper( rxContext, pProvider, Identifier ),
284 m_pProvider( pProvider ),
285 m_pSession( NULL ),
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( );
297 Content::~Content()
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 )
320 #ifndef SYSTEM_CURL
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 );
330 #endif
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 ),
372 xEnv,
373 OUString( ) );
374 else
375 m_pProvider->registerSession( sSessionId, m_pSession );
377 else
379 // Silently fail as the user cancelled the authentication
380 throw uno::RuntimeException( );
383 return m_pSession;
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& )
405 if ( pParent )
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;
412 if ( pProperty )
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 ) )
443 return m_pObject;
445 catch ( uno::RuntimeException& )
447 return m_pObject;
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 ) );
481 if ( pParentFolder )
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 )
488 m_pObject = *it;
492 if ( !m_pObject )
493 throw libcmis::Exception( "Object not found" );
496 else
498 m_pObject = getSession( xEnv )->getRootFolder( );
499 m_sObjectPath = "/";
500 m_sObjectId = OUString( );
504 return m_pObject;
507 bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv )
509 bool bIsFolder = false;
512 libcmis::ObjectPtr obj = getObject( xEnv );
513 if ( obj )
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 ),
522 xEnv,
523 OUString::createFromAscii( e.what( ) ) );
525 return bIsFolder;
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( ) );
561 return updateObj;
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 );
570 sal_Int32 nProps;
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 );
587 if ( obj )
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" );
594 else
595 xRow->appendVoid( rProp );
598 else if ( rProp.Name == "IsFolder" )
602 libcmis::ObjectPtr obj = getObject( xEnv );
603 if ( obj )
604 xRow->appendBoolean( rProp, obj->getBaseType( ) == "cmis:folder" );
605 else
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" );
612 else
613 xRow->appendVoid( rProp );
616 else if ( rProp.Name == "Title" )
618 OUString sTitle;
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( '/' );
648 if ( nPos >= 0 )
649 sTitle = sPath.copy( nPos + 1 );
652 if ( !sTitle.isEmpty( ) )
653 xRow->appendString( rProp, sTitle );
654 else
655 xRow->appendVoid( rProp );
657 else if ( rProp.Name == "ObjectId" )
659 OUString sId;
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 );
680 else
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 ) )
693 bReadOnly = true;
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() );
714 else
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() ) );
733 else
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( );
781 sal_Int32 i = 0;
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( ) )
801 default:
802 case libcmis::PropertyType::String:
803 pCmisProps[i].Type = CMIS_TYPE_STRING;
804 break;
805 case libcmis::PropertyType::Integer:
806 pCmisProps[i].Type = CMIS_TYPE_INTEGER;
807 break;
808 case libcmis::PropertyType::Decimal:
809 pCmisProps[i].Type = CMIS_TYPE_DECIMAL;
810 break;
811 case libcmis::PropertyType::Bool:
812 pCmisProps[i].Type = CMIS_TYPE_BOOL;
813 break;
814 case libcmis::PropertyType::DateTime:
815 pCmisProps[i].Type = CMIS_TYPE_DATETIME;
816 break;
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;
847 if ( aAllowables )
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;
865 if ( aAllowables )
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;
883 if ( aAllowables )
885 bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CheckIn );
887 xRow->appendBoolean( rProp, bAllowed );
889 catch ( const libcmis::Exception& )
891 xRow->appendVoid( rProp );
894 else
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);
926 uno::Any aRet;
928 bool bOpenFolder = (
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 );
938 aRet <<= xSet;
940 else if ( rOpenCommand.Sink.is() )
942 if (
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 ) ) ),
951 xEnv );
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 ) ),
965 xEnv );
968 else
969 SAL_INFO( "ucb.ucp.cmis", "Open falling through ..." );
971 return aRet;
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( ) );
991 if ( !pPwc )
993 ucbhelper::cancelCommandExecution(
994 ucb::IOErrorCode_GENERAL,
995 uno::Sequence< uno::Any >( 0 ),
996 xEnv,
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 ) );
1016 else
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 )
1029 OUString aRet;
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 ),
1039 xEnv,
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 ) );
1052 else
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 ),
1067 xEnv,
1068 OUString::createFromAscii( e.what() ) );
1070 return aRet;
1073 OUString Content::cancelCheckOut( const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1074 throw( uno::Exception )
1076 OUString aRet;
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 ),
1085 xEnv,
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 )
1107 bFound = true;
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 ) );
1116 else
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 ),
1133 xEnv,
1134 OUString::createFromAscii( e.what() ) );
1136 return aRet;
1139 uno::Sequence< document::CmisVersion> Content::getAllVersions( const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1140 throw( uno::Exception, std::exception )
1144 // get the document
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 ),
1151 xEnv,
1152 "Can not get the document" );
1154 vector< libcmis::DocumentPtr > aCmisVersions = pDoc->getAllVersions( );
1155 uno::Sequence< document::CmisVersion > aVersions( aCmisVersions.size( ) );
1156 int i = 0;
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") );
1166 return aVersions;
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 ),
1174 xEnv,
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(
1192 uno::makeAny(
1193 ucb::InteractiveBadTransferURLException(
1194 OUString("Unsupported URL scheme!"),
1195 static_cast< cppu::OWeakObject * >( this ) ) ),
1196 xEnv );
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 ) ) ),
1213 xEnv );
1216 // For transient content, the URL is the one of the parent
1217 if ( m_bTransient )
1219 OUString sNewPath;
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& )
1231 if ( pFolder != 0 )
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 ) ) ),
1240 xEnv );
1242 string newName = it->second->getStrings( ).front( );
1243 string newPath = OUSTR_TO_STDSTR( m_sObjectPath );
1244 if ( !newPath.empty( ) && newPath[ newPath.size( ) - 1 ] != '/' )
1245 newPath += "/";
1246 newPath += newName;
1249 if ( !m_sObjectId.isEmpty( ) )
1250 object = getSession( xEnv )->getObject( OUSTR_TO_STDSTR( m_sObjectId) );
1251 else
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 ) ) ),
1268 xEnv );
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 ) ) ),
1287 xEnv );
1291 else
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 );
1297 if ( bIsFolder )
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 ) ) ),
1309 xEnv );
1312 else
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 ) ) ),
1327 xEnv );
1332 if ( !sNewPath.isEmpty( ) || !m_sObjectId.isEmpty( ) )
1334 // Update the current content: it's no longer transient
1335 m_sObjectPath = sNewPath;
1336 URL aUrl( m_sURL );
1337 aUrl.setObjectPath( m_sObjectPath );
1338 aUrl.setObjectId( m_sObjectId );
1339 m_sURL = aUrl.asString( );
1340 m_pObject.reset( );
1341 m_pObjectType.reset( );
1342 m_pObjectProps.clear( );
1343 m_bTransient = false;
1344 inserted();
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 ),
1383 xEnv,
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 ) );
1404 aRet[ n ] <<= e;
1406 else if ( rValue.Name == "Title" )
1408 OUString aNewTitle;
1409 if (!( rValue.Value >>= aNewTitle ))
1411 aRet[ n ] <<= beans::IllegalTypeException
1412 ( OUString("Property value has wrong type!"),
1413 static_cast< cppu::OWeakObject * >( this ) );
1414 continue;
1417 if ( aNewTitle.getLength() <= 0 )
1419 aRet[ n ] <<= lang::IllegalArgumentException
1420 ( OUString("Empty title not allowed!"),
1421 static_cast< cppu::OWeakObject * >( this ), -1 );
1422 continue;
1426 setCmisProperty( "cmis:name", OUSTR_TO_STDSTR( aNewTitle ), xEnv );
1427 bChanged = true;
1429 else
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 ) );
1434 aRet[ n ] <<= e;
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 ),
1451 xEnv,
1452 OUString::createFromAscii( e.what() ) );
1455 return aRet;
1458 bool Content::feedSink( uno::Reference< uno::XInterface> xSink,
1459 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1461 if ( !xSink.is() )
1462 return false;
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() ) )
1469 return false;
1471 if ( xDataStreamer.is() && !xOut.is() )
1472 xOut = xDataStreamer->getStream()->getOutputStream();
1476 libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject( xEnv ).get() );
1478 if (!document)
1479 return false;
1481 boost::shared_ptr< istream > aIn = document->getContentStream( );
1483 uno::Reference< io::XInputStream > xIn = new ucbhelper::StdInputStream( aIn );
1484 if( !xIn.is( ) )
1485 return false;
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 ),
1498 xEnv,
1499 OUString::createFromAscii( e.what() ) );
1502 return true;
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
1570 ucb::CommandInfo
1571 ( OUString( "getCommandInfo" ),
1572 -1, cppu::UnoType<void>::get() ),
1573 ucb::CommandInfo
1574 ( OUString( "getPropertySetInfo" ),
1575 -1, cppu::UnoType<void>::get() ),
1576 ucb::CommandInfo
1577 ( OUString( "getPropertyValues" ),
1578 -1, cppu::UnoType<uno::Sequence< beans::Property >>::get() ),
1579 ucb::CommandInfo
1580 ( OUString( "setPropertyValues" ),
1581 -1, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() ),
1583 // Optional standard commands
1584 ucb::CommandInfo
1585 ( OUString( "delete" ),
1586 -1, cppu::UnoType<bool>::get() ),
1587 ucb::CommandInfo
1588 ( OUString( "insert" ),
1589 -1, cppu::UnoType<ucb::InsertCommandArgument2>::get() ),
1590 ucb::CommandInfo
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() ),
1600 ucb::CommandInfo
1601 ( OUString( "getAllVersions" ),
1602 -1, cppu::UnoType<uno::Sequence< document::CmisVersion >>::get() ),
1605 // Folder Only, omitted if not a folder
1606 ucb::CommandInfo
1607 ( OUString( "transfer" ),
1608 -1, cppu::UnoType<ucb::TransferInfo>::get() ),
1609 ucb::CommandInfo
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 == "/" )
1623 return parentUrl;
1624 else
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( );
1635 return parentUrl;
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";
1666 return aSNS;
1669 OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException, std::exception )
1671 OUString sRet;
1674 sRet = isFolder( uno::Reference< ucb::XCommandEnvironment >() )
1675 ? OUString(CMIS_FOLDER_TYPE)
1676 : OUString(CMIS_FILE_TYPE);
1678 catch (const uno::RuntimeException&)
1680 throw;
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);
1689 return sRet;
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 );
1699 uno::Any aRet;
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( );
1765 else
1767 libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject( xEnv ).get() );
1768 if (folder)
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 ),
1778 xEnv,
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 );
1807 else
1809 SAL_INFO( "ucb.ucp.cmis", "Unknown command to execute" );
1811 ucbhelper::cancelCommandExecution
1812 ( uno::makeAny( ucb::UnsupportedCommandException
1813 ( OUString(),
1814 static_cast< cppu::OWeakObject * >( this ) ) ),
1815 xEnv );
1818 return aRet;
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;
1842 else
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&)
1887 throw;
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(
1925 OUString("Title"),
1927 cppu::UnoType<OUString>::get(),
1928 beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
1930 // file
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;
1936 // folder
1937 seq[1].Type = CMIS_FOLDER_TYPE;
1938 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1939 seq[1].Properties = props;
1941 return seq;
1944 catch (const uno::RuntimeException&)
1946 throw;
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 >() ) );
1964 if ( 0 != pFolder )
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
1977 URL aUrl( m_sURL );
1978 OUString sPath( m_sObjectPath );
1979 if ( !sPath.endsWith("/") )
1980 sPath += "/";
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() );
1997 return results;
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: */