Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License or as specified alternatively below. You may obtain a copy of
8 : * the License at http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * Major Contributor(s):
16 : * [ Copyright (C) 2011 SUSE <cbosdonnat@suse.com> (initial developer) ]
17 : *
18 : * All Rights Reserved.
19 : *
20 : * For minor contributions see the git repository.
21 : *
22 : * Alternatively, the contents of this file may be used under the terms of
23 : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
24 : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
25 : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
26 : * instead of those above.
27 : */
28 :
29 : #include <cstdio>
30 :
31 : #include <com/sun/star/beans/PropertyAttribute.hpp>
32 : #include <com/sun/star/beans/PropertyValue.hpp>
33 : #include <com/sun/star/beans/PropertyValues.hpp>
34 : #include <com/sun/star/beans/XPropertySetInfo.hpp>
35 : #include <com/sun/star/io/XActiveDataSink.hpp>
36 : #include <com/sun/star/io/XActiveDataStreamer.hpp>
37 : #include <com/sun/star/lang/IllegalAccessException.hpp>
38 : #include <com/sun/star/task/InteractionClassification.hpp>
39 : #include <com/sun/star/ucb/ContentInfo.hpp>
40 : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
41 : #include <com/sun/star/ucb/InsertCommandArgument2.hpp>
42 : #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
43 : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
44 : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
45 : #include <com/sun/star/ucb/NameClash.hpp>
46 : #include <com/sun/star/ucb/NameClashException.hpp>
47 : #include <com/sun/star/ucb/OpenMode.hpp>
48 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
49 : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
50 : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
51 : #include <com/sun/star/ucb/XCommandInfo.hpp>
52 : #include <com/sun/star/ucb/XDynamicResultSet.hpp>
53 :
54 : #include <libcmis/document.hxx>
55 :
56 : #include <comphelper/processfactory.hxx>
57 : #include <ucbhelper/cancelcommandexecution.hxx>
58 : #include <ucbhelper/content.hxx>
59 : #include <ucbhelper/contentidentifier.hxx>
60 : #include <ucbhelper/std_inputstream.hxx>
61 : #include <ucbhelper/std_outputstream.hxx>
62 : #include <ucbhelper/propertyvalueset.hxx>
63 :
64 : #include "auth_provider.hxx"
65 : #include "cmis_content.hxx"
66 : #include "cmis_provider.hxx"
67 : #include "cmis_resultset.hxx"
68 :
69 : #define OUSTR_TO_STDSTR(s) string( rtl::OUStringToOString( s, RTL_TEXTENCODING_UTF8 ).getStr() )
70 : #define STD_TO_OUSTR( str ) rtl::OUString( str.c_str(), str.length( ), RTL_TEXTENCODING_UTF8 )
71 :
72 : using namespace com::sun::star;
73 : using namespace std;
74 :
75 : namespace
76 : {
77 0 : util::DateTime lcl_boostToUnoTime( boost::posix_time::ptime boostTime )
78 : {
79 0 : util::DateTime unoTime;
80 0 : unoTime.Year = boostTime.date().year();
81 0 : unoTime.Month = boostTime.date().month();
82 0 : unoTime.Day = boostTime.date().day();
83 0 : unoTime.Hours = boostTime.time_of_day().hours();
84 0 : unoTime.Minutes = boostTime.time_of_day().minutes();
85 0 : unoTime.Seconds = boostTime.time_of_day().seconds();
86 :
87 0 : long total_milli = boostTime.time_of_day().total_milliseconds( );
88 0 : long milli = total_milli - boostTime.time_of_day().total_seconds( );
89 0 : long hundredthSeconds = milli / 10;
90 :
91 0 : unoTime.HundredthSeconds = hundredthSeconds;
92 :
93 0 : return unoTime;
94 : }
95 :
96 0 : uno::Any lcl_cmisPropertyToUno( libcmis::PropertyPtr pProperty )
97 : {
98 0 : uno::Any aValue;
99 0 : bool bMultiValued = pProperty->getPropertyType( )->isMultiValued( );
100 0 : switch ( pProperty->getPropertyType( )->getType( ) )
101 : {
102 : default:
103 : case libcmis::PropertyType::String:
104 : {
105 0 : vector< string > aCmisStrings = pProperty->getStrings( );
106 0 : if ( bMultiValued )
107 : {
108 0 : uno::Sequence< rtl::OUString > aStrings( aCmisStrings.size( ) );
109 0 : rtl::OUString* aStringsArr = aStrings.getArray( );
110 0 : sal_Int32 i = 0;
111 0 : for ( vector< string >::iterator it = aCmisStrings.begin( );
112 0 : it != aCmisStrings.end( ); ++it, ++i )
113 : {
114 0 : string str = *it;
115 0 : aStringsArr[i] = STD_TO_OUSTR( str );
116 0 : }
117 0 : aValue <<= aStrings;
118 : }
119 0 : else if ( !aCmisStrings.empty( ) )
120 : {
121 0 : aValue <<= STD_TO_OUSTR( aCmisStrings.front( ) );
122 0 : }
123 : }
124 0 : break;
125 : case libcmis::PropertyType::Integer:
126 : {
127 0 : vector< long > aCmisLongs = pProperty->getLongs( );
128 0 : if ( bMultiValued )
129 : {
130 0 : uno::Sequence< sal_Int64 > aLongs( aCmisLongs.size( ) );
131 0 : sal_Int64* aLongsArr = aLongs.getArray( );
132 0 : sal_Int32 i = 0;
133 0 : for ( vector< long >::iterator it = aCmisLongs.begin( );
134 0 : it != aCmisLongs.end( ); ++it, ++i )
135 : {
136 0 : aLongsArr[i] = *it;
137 : }
138 0 : aValue <<= aLongs;
139 : }
140 0 : else if ( !aCmisLongs.empty( ) )
141 : {
142 0 : aValue <<= aCmisLongs.front( );
143 0 : }
144 : }
145 0 : break;
146 : case libcmis::PropertyType::Decimal:
147 : {
148 0 : vector< double > aCmisDoubles = pProperty->getDoubles( );
149 0 : if ( bMultiValued )
150 : {
151 0 : uno::Sequence< double > aDoubles( aCmisDoubles.size( ) );
152 0 : double* aDoublesArr = aDoubles.getArray( );
153 0 : sal_Int32 i = 0;
154 0 : for ( vector< double >::iterator it = aCmisDoubles.begin( );
155 0 : it != aCmisDoubles.end( ); ++it, ++i )
156 : {
157 0 : aDoublesArr[i] = *it;
158 : }
159 0 : aValue <<= aDoubles;
160 : }
161 0 : else if ( !aCmisDoubles.empty( ) )
162 : {
163 0 : aValue <<= aCmisDoubles.front( );
164 0 : }
165 : }
166 0 : break;
167 : case libcmis::PropertyType::Bool:
168 : {
169 0 : vector< bool > aCmisBools = pProperty->getBools( );
170 0 : if ( bMultiValued )
171 : {
172 0 : uno::Sequence< sal_Bool > aBools( aCmisBools.size( ) );
173 0 : sal_Bool* aBoolsArr = aBools.getArray( );
174 0 : sal_Int32 i = 0;
175 0 : for ( vector< bool >::iterator it = aCmisBools.begin( );
176 0 : it != aCmisBools.end( ); ++it, ++i )
177 : {
178 0 : aBoolsArr[i] = *it;
179 : }
180 0 : aValue <<= aBools;
181 : }
182 0 : else if ( !aCmisBools.empty( ) )
183 : {
184 0 : aValue <<= sal_Bool( aCmisBools.front( ) );
185 0 : }
186 : }
187 0 : break;
188 : case libcmis::PropertyType::DateTime:
189 : {
190 0 : vector< boost::posix_time::ptime > aCmisTimes = pProperty->getDateTimes( );
191 0 : if ( bMultiValued )
192 : {
193 0 : uno::Sequence< util::DateTime > aTimes( aCmisTimes.size( ) );
194 0 : util::DateTime* aTimesArr = aTimes.getArray( );
195 0 : sal_Int32 i = 0;
196 0 : for ( vector< boost::posix_time::ptime >::iterator it = aCmisTimes.begin( );
197 0 : it != aCmisTimes.end( ); ++it, ++i )
198 : {
199 0 : aTimesArr[i] = lcl_boostToUnoTime( *it );
200 : }
201 0 : aValue <<= aTimes;
202 : }
203 0 : else if ( !aCmisTimes.empty( ) )
204 : {
205 0 : aValue <<= lcl_boostToUnoTime( aCmisTimes.front( ) );
206 0 : }
207 : }
208 0 : break;
209 : }
210 0 : return aValue;
211 : }
212 : }
213 :
214 : namespace cmis
215 : {
216 0 : Content::Content( const uno::Reference< uno::XComponentContext >& rxContext,
217 : ContentProvider *pProvider, const uno::Reference< ucb::XContentIdentifier >& Identifier,
218 : libcmis::ObjectPtr pObject )
219 : throw ( ucb::ContentCreationException )
220 : : ContentImplHelper( rxContext, pProvider, Identifier ),
221 : m_pProvider( pProvider ),
222 : m_pSession( NULL ),
223 : m_pObject( pObject ),
224 0 : m_sURL( Identifier->getContentIdentifier( ) ),
225 0 : m_aURL( Identifier->getContentIdentifier( ) ),
226 : m_bTransient( false ),
227 0 : m_bIsFolder( false )
228 : {
229 : SAL_INFO( "cmisucp", "Content::Content() " << m_sURL );
230 :
231 0 : m_sObjectPath = m_aURL.getObjectPath( );
232 0 : m_sObjectId = m_aURL.getObjectId( );
233 0 : }
234 :
235 0 : Content::Content( const uno::Reference< uno::XComponentContext >& rxContext, ContentProvider *pProvider,
236 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
237 : sal_Bool bIsFolder )
238 : throw ( ucb::ContentCreationException )
239 : : ContentImplHelper( rxContext, pProvider, Identifier ),
240 : m_pProvider( pProvider ),
241 : m_pSession( NULL ),
242 0 : m_sURL( Identifier->getContentIdentifier( ) ),
243 0 : m_aURL( Identifier->getContentIdentifier( ) ),
244 : m_bTransient( true ),
245 0 : m_bIsFolder( bIsFolder )
246 : {
247 : SAL_INFO( "cmisucp", "Content::Content() " << m_sURL );
248 :
249 0 : m_sObjectPath = m_aURL.getObjectPath( );
250 0 : m_sObjectId = m_aURL.getObjectId( );
251 0 : }
252 :
253 0 : Content::~Content()
254 : {
255 0 : }
256 :
257 0 : libcmis::Session* Content::getSession( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
258 : {
259 : // Look for a cached session, key is binding url + repo id
260 0 : rtl::OUString sSessionId = m_aURL.getBindingUrl( ) + m_aURL.getRepositoryId( );
261 0 : if ( NULL == m_pSession )
262 0 : m_pSession = m_pProvider->getSession( sSessionId );
263 :
264 0 : if ( NULL == m_pSession )
265 : {
266 : // Get the auth credentials
267 0 : AuthProvider authProvider( xEnv, m_xIdentifier->getContentIdentifier( ), m_aURL.getBindingUrl( ) );
268 :
269 0 : string rUsername = OUSTR_TO_STDSTR( m_aURL.getUsername( ) );
270 0 : string rPassword = OUSTR_TO_STDSTR( m_aURL.getPassword( ) );
271 0 : if ( authProvider.authenticationQuery( rUsername, rPassword ) )
272 : {
273 : // Initiate a CMIS session and register it as we found nothing
274 : m_pSession = libcmis::SessionFactory::createSession(
275 0 : OUSTR_TO_STDSTR( m_aURL.getBindingUrl( ) ),
276 0 : rUsername, rPassword, OUSTR_TO_STDSTR( m_aURL.getRepositoryId( ) ) );
277 0 : if ( m_pSession == NULL )
278 : ucbhelper::cancelCommandExecution(
279 : ucb::IOErrorCode_INVALID_DEVICE,
280 : uno::Sequence< uno::Any >( 0 ),
281 : xEnv,
282 0 : rtl::OUString( ) );
283 0 : m_pProvider->registerSession( sSessionId, m_pSession );
284 : }
285 : else
286 : {
287 : // Silently fail as the user cancelled the authentication
288 0 : throw uno::RuntimeException( );
289 0 : }
290 : }
291 0 : return m_pSession;
292 : }
293 :
294 0 : libcmis::ObjectTypePtr Content::getObjectType( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
295 : {
296 0 : if ( NULL == m_pObjectType.get( ) && m_bTransient )
297 : {
298 0 : string typeId = m_bIsFolder ? "cmis:folder" : "cmis:document";
299 0 : m_pObjectType = getSession( xEnv )->getType( typeId );
300 : }
301 0 : return m_pObjectType;
302 : }
303 :
304 :
305 0 : libcmis::ObjectPtr Content::getObject( const uno::Reference< ucb::XCommandEnvironment >& xEnv ) throw ( libcmis::Exception )
306 : {
307 0 : if ( !m_pObject.get() )
308 : {
309 0 : if ( !m_sObjectPath.isEmpty( ) )
310 0 : m_pObject = getSession( xEnv )->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) );
311 0 : else if (!m_sObjectId.isEmpty( ) )
312 0 : m_pObject = getSession( xEnv )->getObject( OUSTR_TO_STDSTR( m_sObjectId ) );
313 : else
314 : {
315 0 : m_pObject = getSession( xEnv )->getRootFolder( );
316 0 : m_sObjectPath = "/";
317 0 : m_sObjectId = rtl::OUString( );
318 : }
319 : }
320 :
321 0 : return m_pObject;
322 : }
323 :
324 0 : bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv )
325 : {
326 0 : bool bIsFolder = false;
327 : try
328 : {
329 0 : bIsFolder = getObject( xEnv )->getBaseType( ) == "cmis:folder";
330 : }
331 0 : catch ( const libcmis::Exception& e )
332 : {
333 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
334 : ucbhelper::cancelCommandExecution(
335 : ucb::IOErrorCode_GENERAL,
336 : uno::Sequence< uno::Any >( 0 ),
337 : xEnv,
338 0 : rtl::OUString::createFromAscii( e.what( ) ) );
339 : }
340 0 : return bIsFolder;
341 : }
342 :
343 0 : uno::Any Content::getBadArgExcept()
344 : {
345 : return uno::makeAny( lang::IllegalArgumentException(
346 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Wrong argument type!")),
347 0 : static_cast< cppu::OWeakObject * >( this ), -1) );
348 : }
349 :
350 0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
351 : const uno::Sequence< beans::Property >& rProperties,
352 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
353 : {
354 0 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( m_xContext );
355 :
356 : sal_Int32 nProps;
357 : const beans::Property* pProps;
358 :
359 0 : nProps = rProperties.getLength();
360 0 : pProps = rProperties.getConstArray();
361 :
362 0 : for( sal_Int32 n = 0; n < nProps; ++n )
363 : {
364 0 : const beans::Property& rProp = pProps[ n ];
365 :
366 : try
367 : {
368 0 : if ( rProp.Name == "IsDocument" )
369 : {
370 : try
371 : {
372 0 : xRow->appendBoolean( rProp, getObject( xEnv )->getBaseType( ) == "cmis:document" );
373 : }
374 0 : catch ( const libcmis::Exception& )
375 : {
376 0 : if ( m_pObjectType.get( ) )
377 0 : xRow->appendBoolean( rProp, getObjectType( xEnv )->getBaseType()->getId( ) == "cmis:document" );
378 : else
379 0 : xRow->appendVoid( rProp );
380 : }
381 : }
382 0 : else if ( rProp.Name == "IsFolder" )
383 : {
384 : try
385 : {
386 0 : xRow->appendBoolean( rProp, getObject( xEnv )->getBaseType( ) == "cmis:folder" );
387 : }
388 0 : catch ( const libcmis::Exception& )
389 : {
390 0 : if ( m_pObjectType.get( ) )
391 0 : xRow->appendBoolean( rProp, getObjectType( xEnv )->getBaseType()->getId( ) == "cmis:folder" );
392 : else
393 0 : xRow->appendVoid( rProp );
394 : }
395 : }
396 0 : else if ( rProp.Name == "Title" )
397 : {
398 0 : rtl::OUString sTitle;
399 : try
400 : {
401 0 : sTitle = STD_TO_OUSTR( getObject( xEnv )->getName() );
402 : }
403 0 : catch ( const libcmis::Exception& )
404 : {
405 0 : if ( !m_pObjectProps.empty() )
406 : {
407 0 : map< string, libcmis::PropertyPtr >::iterator it = m_pObjectProps.find( "cmis:name" );
408 0 : if ( it != m_pObjectProps.end( ) )
409 : {
410 0 : vector< string > values = it->second->getStrings( );
411 0 : if ( !values.empty() )
412 0 : sTitle = STD_TO_OUSTR( values.front( ) );
413 : }
414 : }
415 : }
416 :
417 : // Nothing worked... get it from the path
418 0 : if ( sTitle.isEmpty( ) )
419 : {
420 0 : rtl::OUString sPath = m_sObjectPath;
421 :
422 : // Get rid of the trailing slash problem
423 0 : if ( sPath[ sPath.getLength( ) - 1 ] == '/' )
424 0 : sPath = sPath.copy( 0, sPath.getLength() - 1 );
425 :
426 : // Get the last segment
427 0 : sal_Int32 nPos = sPath.lastIndexOf( '/' );
428 0 : if ( nPos >= 0 )
429 0 : sTitle = sPath.copy( nPos + 1 );
430 : }
431 :
432 0 : if ( !sTitle.isEmpty( ) )
433 0 : xRow->appendString( rProp, sTitle );
434 : else
435 0 : xRow->appendVoid( rProp );
436 : }
437 0 : else if ( rProp.Name == "TitleOnServer" )
438 : {
439 0 : string path;
440 : try
441 : {
442 0 : vector< string > paths = getObject( xEnv )->getPaths( );
443 0 : if ( !paths.empty( ) )
444 0 : path = paths.front( );
445 : else
446 0 : path = getObject( xEnv )->getName( );
447 :
448 0 : xRow->appendString( rProp, STD_TO_OUSTR( path ) );
449 : }
450 0 : catch ( const libcmis::Exception& )
451 : {
452 0 : xRow->appendVoid( rProp );
453 0 : }
454 : }
455 0 : else if ( rProp.Name == "IsReadOnly" )
456 : {
457 0 : boost::shared_ptr< libcmis::AllowableActions > allowableActions = getObject( xEnv )->getAllowableActions( );
458 0 : sal_Bool bReadOnly = sal_False;
459 0 : if ( !allowableActions->isAllowed( libcmis::ObjectAction::SetContentStream ) &&
460 0 : !allowableActions->isAllowed( libcmis::ObjectAction::CheckIn ) )
461 0 : bReadOnly = sal_True;
462 :
463 0 : xRow->appendBoolean( rProp, bReadOnly );
464 : }
465 0 : else if ( rProp.Name == "DateCreated" )
466 : {
467 0 : util::DateTime aTime = lcl_boostToUnoTime( getObject( xEnv )->getCreationDate( ) );
468 0 : xRow->appendTimestamp( rProp, aTime );
469 : }
470 0 : else if ( rProp.Name == "DateModified" )
471 : {
472 0 : util::DateTime aTime = lcl_boostToUnoTime( getObject( xEnv )->getLastModificationDate( ) );
473 0 : xRow->appendTimestamp( rProp, aTime );
474 : }
475 0 : else if ( rProp.Name == "Size" )
476 : {
477 : try
478 : {
479 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject( xEnv ).get( ) );
480 0 : if ( NULL != document )
481 0 : xRow->appendLong( rProp, document->getContentLength() );
482 : else
483 0 : xRow->appendVoid( rProp );
484 : }
485 0 : catch ( const libcmis::Exception& )
486 : {
487 0 : xRow->appendVoid( rProp );
488 : }
489 : }
490 0 : else if ( rProp.Name == "CreatableContentsInfo" )
491 : {
492 0 : xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) );
493 : }
494 0 : else if ( rProp.Name == "MediaType" )
495 : {
496 : try
497 : {
498 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject( xEnv ).get( ) );
499 0 : if ( NULL != document )
500 0 : xRow->appendString( rProp, STD_TO_OUSTR( document->getContentType() ) );
501 : else
502 0 : xRow->appendVoid( rProp );
503 : }
504 0 : catch ( const libcmis::Exception& )
505 : {
506 0 : xRow->appendVoid( rProp );
507 : }
508 : }
509 0 : else if ( rProp.Name == "CmisPropertiesValues" )
510 : {
511 : try
512 : {
513 0 : libcmis::ObjectPtr object = getObject( xEnv );
514 0 : map< string, libcmis::PropertyPtr >& aProperties = object->getProperties( );
515 0 : beans::PropertyValues aCmisProperties( aProperties.size( ) );
516 0 : beans::PropertyValue* pCmisProps = aCmisProperties.getArray( );
517 0 : sal_Int32 i = 0;
518 0 : for ( map< string, libcmis::PropertyPtr >::iterator it = aProperties.begin();
519 0 : it != aProperties.end( ); ++it, ++i )
520 : {
521 0 : string name = it->first;
522 0 : pCmisProps[i].Name = STD_TO_OUSTR( name );
523 0 : pCmisProps[i].Value = lcl_cmisPropertyToUno( it->second );
524 0 : }
525 0 : xRow->appendObject( rProp.Name, uno::makeAny( aCmisProperties ) );
526 : }
527 0 : catch ( const libcmis::Exception& )
528 : {
529 0 : xRow->appendVoid( rProp );
530 : }
531 : }
532 0 : else if ( rProp.Name == "CmisPropertiesDisplayNames" )
533 : {
534 : try
535 : {
536 0 : libcmis::ObjectPtr object = getObject( xEnv );
537 0 : map< string, libcmis::PropertyPtr >& aProperties = object->getProperties( );
538 0 : beans::PropertyValues aCmisProperties( aProperties.size( ) );
539 0 : beans::PropertyValue* pCmisProps = aCmisProperties.getArray( );
540 0 : sal_Int32 i = 0;
541 0 : for ( map< string, libcmis::PropertyPtr >::iterator it = aProperties.begin();
542 0 : it != aProperties.end( ); ++it, ++i )
543 : {
544 0 : string name = it->first;
545 0 : string displayName = it->second->getPropertyType()->getDisplayName( );
546 0 : pCmisProps[i].Name = STD_TO_OUSTR( name );
547 0 : pCmisProps[i].Value = uno::makeAny( STD_TO_OUSTR( displayName ) );
548 0 : }
549 0 : xRow->appendObject( rProp.Name, uno::makeAny( aCmisProperties ) );
550 : }
551 0 : catch ( const libcmis::Exception& )
552 : {
553 0 : xRow->appendVoid( rProp );
554 : }
555 : }
556 0 : else if ( rProp.Name == "IsVersionable" )
557 : {
558 : try
559 : {
560 0 : libcmis::ObjectPtr object = getObject( xEnv );
561 0 : sal_Bool bIsVersionable = object->getTypeDescription( )->isVersionable( );
562 0 : xRow->appendBoolean( rProp, bIsVersionable );
563 : }
564 0 : catch ( const libcmis::Exception& )
565 : {
566 0 : xRow->appendVoid( rProp );
567 : }
568 : }
569 0 : else if ( rProp.Name == "CanCheckOut" )
570 : {
571 : try
572 : {
573 0 : libcmis::ObjectPtr pObject = getObject( xEnv );
574 0 : libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( );
575 0 : bool bAllowed = false;
576 0 : if ( aAllowables )
577 : {
578 0 : bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CheckOut );
579 : }
580 0 : xRow->appendBoolean( rProp, bAllowed );
581 : }
582 0 : catch ( const libcmis::Exception& )
583 : {
584 0 : xRow->appendVoid( rProp );
585 : }
586 : }
587 0 : else if ( rProp.Name == "CanCancelCheckOut" )
588 : {
589 : try
590 : {
591 0 : libcmis::ObjectPtr pObject = getObject( xEnv );
592 0 : libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( );
593 0 : bool bAllowed = false;
594 0 : if ( aAllowables )
595 : {
596 0 : bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CancelCheckOut );
597 : }
598 0 : xRow->appendBoolean( rProp, bAllowed );
599 : }
600 0 : catch ( const libcmis::Exception& )
601 : {
602 0 : xRow->appendVoid( rProp );
603 : }
604 : }
605 0 : else if ( rProp.Name == "CanCheckIn" )
606 : {
607 : try
608 : {
609 0 : libcmis::ObjectPtr pObject = getObject( xEnv );
610 0 : libcmis::AllowableActionsPtr aAllowables = pObject->getAllowableActions( );
611 0 : bool bAllowed = false;
612 0 : if ( aAllowables )
613 : {
614 0 : bAllowed = aAllowables->isAllowed( libcmis::ObjectAction::CheckIn );
615 : }
616 0 : xRow->appendBoolean( rProp, bAllowed );
617 : }
618 0 : catch ( const libcmis::Exception& )
619 : {
620 0 : xRow->appendVoid( rProp );
621 : }
622 : }
623 : else
624 : SAL_INFO( "cmisucp", "Looking for unsupported property " << rProp.Name );
625 : }
626 0 : catch (const libcmis::Exception&)
627 : {
628 0 : xRow->appendVoid( rProp );
629 : }
630 : }
631 :
632 0 : return uno::Reference< sdbc::XRow >( xRow.get() );
633 : }
634 :
635 0 : bool Content::exists( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
636 : {
637 0 : bool bExists = true;
638 : try
639 : {
640 0 : if ( !m_sObjectPath.isEmpty( ) )
641 0 : m_pSession->getObjectByPath( OUSTR_TO_STDSTR( m_sObjectPath ) );
642 0 : else if ( !m_sObjectId.isEmpty( ) )
643 0 : getSession( xEnv )->getObject( OUSTR_TO_STDSTR( m_sObjectId ) );
644 : // No need to handle the root folder case... how can it not exists?
645 : }
646 0 : catch ( const libcmis::Exception& )
647 : {
648 0 : bExists = false;
649 : }
650 :
651 0 : return bExists;
652 : }
653 :
654 0 : uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand,
655 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
656 : throw( uno::Exception )
657 : {
658 0 : bool bIsFolder = isFolder( xEnv );
659 :
660 : // Handle the case of the non-existing file
661 0 : if ( !exists( xEnv ) )
662 : {
663 0 : uno::Sequence< uno::Any > aArgs( 1 );
664 0 : aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
665 : uno::Any aErr = uno::makeAny(
666 : ucb::InteractiveAugmentedIOException(rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
667 : task::InteractionClassification_ERROR,
668 : bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs)
669 0 : );
670 :
671 0 : ucbhelper::cancelCommandExecution(aErr, xEnv);
672 : }
673 :
674 0 : uno::Any aRet;
675 :
676 : sal_Bool bOpenFolder = (
677 : ( rOpenCommand.Mode == ucb::OpenMode::ALL ) ||
678 : ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
679 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS )
680 0 : );
681 :
682 0 : if ( bOpenFolder && bIsFolder )
683 : {
684 : uno::Reference< ucb::XDynamicResultSet > xSet
685 0 : = new DynamicResultSet(m_xContext, this, rOpenCommand, xEnv );
686 0 : aRet <<= xSet;
687 : }
688 0 : else if ( rOpenCommand.Sink.is() )
689 : {
690 0 : if (
691 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
692 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE )
693 : )
694 : {
695 : ucbhelper::cancelCommandExecution(
696 : uno::makeAny ( ucb::UnsupportedOpenModeException
697 : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
698 : sal_Int16( rOpenCommand.Mode ) ) ),
699 0 : xEnv );
700 : }
701 :
702 0 : if ( !feedSink( rOpenCommand.Sink, xEnv ) )
703 : {
704 : // Note: rOpenCommand.Sink may contain an XStream
705 : // implementation. Support for this type of
706 : // sink is optional...
707 : SAL_INFO( "cmisucp", "Failed to copy data to sink" );
708 :
709 : ucbhelper::cancelCommandExecution(
710 : uno::makeAny (ucb::UnsupportedDataSinkException
711 : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ),
712 : rOpenCommand.Sink ) ),
713 0 : xEnv );
714 : }
715 : }
716 : else
717 : SAL_INFO( "cmisucp", "Open falling through ..." );
718 :
719 0 : return aRet;
720 : }
721 :
722 0 : rtl::OUString Content::checkIn( const ucb::CheckinArgument& rArg,
723 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
724 : throw( uno::Exception )
725 : {
726 0 : ucbhelper::Content aSourceContent( rArg.SourceURL, xEnv, comphelper::getProcessComponentContext( ) );
727 0 : uno::Reference< io::XInputStream > xIn = aSourceContent.openStream( );
728 :
729 0 : libcmis::ObjectPtr object;
730 : try
731 : {
732 0 : object = getObject( xEnv );
733 : }
734 0 : catch ( const libcmis::Exception& )
735 : {
736 : }
737 :
738 0 : libcmis::Document* pPwc = dynamic_cast< libcmis::Document* >( object.get( ) );
739 0 : if ( !pPwc )
740 : {
741 : ucbhelper::cancelCommandExecution(
742 : ucb::IOErrorCode_GENERAL,
743 : uno::Sequence< uno::Any >( 0 ),
744 : xEnv,
745 0 : "Checkin only supported by documents" );
746 : }
747 :
748 0 : boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) );
749 0 : uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut );
750 0 : copyData( xIn, xOutput );
751 :
752 0 : map< string, libcmis::PropertyPtr > newProperties;
753 : libcmis::DocumentPtr pDoc = pPwc->checkIn( rArg.MajorVersion, OUSTR_TO_STDSTR( rArg.VersionComment ), newProperties,
754 0 : pOut, OUSTR_TO_STDSTR( rArg.MimeType ), OUSTR_TO_STDSTR( rArg.NewTitle ) );
755 :
756 : // Get the URL and send it back as a result
757 0 : URL aCmisUrl( m_sURL );
758 0 : vector< string > aPaths = pDoc->getPaths( );
759 0 : if ( !aPaths.empty() )
760 : {
761 0 : string sPath = aPaths.front( );
762 0 : aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) );
763 : }
764 : else
765 : {
766 : // We may have unfiled document depending on the server, those
767 : // won't have any path, use their ID instead
768 0 : string sId = pDoc->getId( );
769 0 : aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) );
770 : }
771 0 : return aCmisUrl.asString( );
772 : }
773 :
774 0 : rtl::OUString Content::checkOut( const uno::Reference< ucb::XCommandEnvironment > & xEnv )
775 : throw( uno::Exception )
776 : {
777 0 : rtl::OUString aRet;
778 : try
779 : {
780 : // Checkout the document if possible
781 0 : libcmis::DocumentPtr pDoc = boost::dynamic_pointer_cast< libcmis::Document >( getObject( xEnv ) );
782 0 : if ( pDoc.get( ) == NULL )
783 : {
784 : ucbhelper::cancelCommandExecution(
785 : ucb::IOErrorCode_GENERAL,
786 : uno::Sequence< uno::Any >( 0 ),
787 : xEnv,
788 0 : "Checkout only supported by documents" );
789 : }
790 0 : libcmis::DocumentPtr pPwc = pDoc->checkOut( );
791 :
792 : // Compute the URL of the Private Working Copy (PWC)
793 0 : URL aCmisUrl( m_sURL );
794 0 : vector< string > aPaths = pPwc->getPaths( );
795 0 : if ( !aPaths.empty() )
796 : {
797 0 : string sPath = aPaths.front( );
798 0 : aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) );
799 : }
800 : else
801 : {
802 : // We may have unfiled PWC depending on the server, those
803 : // won't have any path, use their ID instead
804 0 : string sId = pPwc->getId( );
805 0 : aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) );
806 : }
807 0 : aRet = aCmisUrl.asString( );
808 : }
809 0 : catch ( const libcmis::Exception& e )
810 : {
811 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
812 : ucbhelper::cancelCommandExecution(
813 : ucb::IOErrorCode_GENERAL,
814 : uno::Sequence< uno::Any >( 0 ),
815 : xEnv,
816 0 : rtl::OUString::createFromAscii( e.what() ) );
817 : }
818 0 : return aRet;
819 : }
820 :
821 0 : rtl::OUString Content::cancelCheckOut( const uno::Reference< ucb::XCommandEnvironment > & xEnv )
822 : throw( uno::Exception )
823 : {
824 0 : rtl::OUString aRet;
825 : try
826 : {
827 0 : libcmis::DocumentPtr pPwc = boost::dynamic_pointer_cast< libcmis::Document >( getObject( xEnv ) );
828 0 : if ( pPwc.get( ) == NULL )
829 : {
830 : ucbhelper::cancelCommandExecution(
831 : ucb::IOErrorCode_GENERAL,
832 : uno::Sequence< uno::Any >( 0 ),
833 : xEnv,
834 0 : "CancelCheckout only supported by documents" );
835 : }
836 0 : pPwc->cancelCheckout( );
837 :
838 : // Get the Original document (latest version)
839 0 : vector< libcmis::DocumentPtr > aVersions = pPwc->getAllVersions( );
840 0 : bool bFound = false;
841 0 : for ( vector< libcmis::DocumentPtr >::iterator it = aVersions.begin();
842 0 : it != aVersions.end( ) && !bFound; ++it )
843 : {
844 0 : libcmis::DocumentPtr pVersion = *it;
845 0 : map< string, libcmis::PropertyPtr > aProps = pVersion->getProperties( );
846 0 : bool bIsLatestVersion = false;
847 0 : map< string, libcmis::PropertyPtr >::iterator propIt = aProps.find( string( "cmis:isLatestVersion" ) );
848 0 : if ( propIt != aProps.end( ) && !propIt->second->getBools( ).empty( ) )
849 : {
850 0 : bIsLatestVersion = propIt->second->getBools( ).front( );
851 : }
852 :
853 0 : if ( bIsLatestVersion )
854 : {
855 0 : bFound = true;
856 : // Compute the URL of the Document
857 0 : URL aCmisUrl( m_sURL );
858 0 : vector< string > aPaths = pVersion->getPaths( );
859 0 : if ( !aPaths.empty() )
860 : {
861 0 : string sPath = aPaths.front( );
862 0 : aCmisUrl.setObjectPath( STD_TO_OUSTR( sPath ) );
863 : }
864 : else
865 : {
866 : // We may have unfiled doc depending on the server, those
867 : // won't have any path, use their ID instead
868 0 : string sId = pVersion->getId( );
869 0 : aCmisUrl.setObjectId( STD_TO_OUSTR( sId ) );
870 : }
871 0 : aRet = aCmisUrl.asString( );
872 : }
873 0 : }
874 : }
875 0 : catch ( const libcmis::Exception& e )
876 : {
877 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
878 : ucbhelper::cancelCommandExecution(
879 : ucb::IOErrorCode_GENERAL,
880 : uno::Sequence< uno::Any >( 0 ),
881 : xEnv,
882 0 : rtl::OUString::createFromAscii( e.what() ) );
883 : }
884 0 : return aRet;
885 : }
886 :
887 0 : void Content::transfer( const ucb::TransferInfo& rTransferInfo,
888 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
889 : throw( uno::Exception )
890 : {
891 : // If the source isn't on the same CMIS repository, then simply copy
892 0 : INetURLObject aSourceUrl( rTransferInfo.SourceURL );
893 0 : if ( aSourceUrl.GetProtocol() != INET_PROT_CMIS )
894 : {
895 0 : rtl::OUString sSrcBindingUrl = URL( rTransferInfo.SourceURL ).getBindingUrl( );
896 0 : if ( sSrcBindingUrl != m_aURL.getBindingUrl( ) )
897 : {
898 : ucbhelper::cancelCommandExecution(
899 : uno::makeAny(
900 : ucb::InteractiveBadTransferURLException(
901 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
902 : "Unsupported URL scheme!" )),
903 : static_cast< cppu::OWeakObject * >( this ) ) ),
904 0 : xEnv );
905 0 : }
906 : }
907 :
908 0 : SAL_INFO( "cmisucp", "TODO - Content::transfer()" );
909 0 : }
910 :
911 0 : void Content::insert( const uno::Reference< io::XInputStream > & xInputStream,
912 : sal_Bool bReplaceExisting, const rtl::OUString& rMimeType,
913 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
914 : throw( uno::Exception )
915 : {
916 0 : if ( !xInputStream.is() )
917 : {
918 : ucbhelper::cancelCommandExecution( uno::makeAny
919 : ( ucb::MissingInputStreamException
920 : ( rtl::OUString(), static_cast< cppu::OWeakObject * >( this ) ) ),
921 0 : xEnv );
922 : }
923 :
924 : // For transient content, the URL is the one of the parent
925 0 : if ( m_bTransient )
926 : {
927 0 : rtl::OUString sNewPath;
928 :
929 : // Try to get the object from the server if there is any
930 0 : libcmis::Folder* pFolder = NULL;
931 : try
932 : {
933 0 : pFolder = dynamic_cast< libcmis::Folder* >( getObject( xEnv ).get( ) );
934 : }
935 0 : catch ( const libcmis::Exception& )
936 : {
937 : }
938 :
939 0 : if ( pFolder != NULL )
940 : {
941 0 : map< string, libcmis::PropertyPtr >::iterator it = m_pObjectProps.find( "cmis:name" );
942 0 : if ( it == m_pObjectProps.end( ) )
943 : {
944 : ucbhelper::cancelCommandExecution( uno::makeAny
945 : ( uno::RuntimeException( "Missing name property",
946 : static_cast< cppu::OWeakObject * >( this ) ) ),
947 0 : xEnv );
948 : }
949 0 : string newName = it->second->getStrings( ).front( );
950 0 : string newPath = pFolder->getPath( );
951 0 : if ( newPath[ newPath.size( ) - 1 ] != '/' )
952 0 : newPath += "/";
953 0 : newPath += newName;
954 :
955 0 : libcmis::ObjectPtr object;
956 : try
957 : {
958 0 : object = getSession( xEnv )->getObjectByPath( newPath );
959 0 : sNewPath = STD_TO_OUSTR( newPath );
960 : }
961 0 : catch ( const libcmis::Exception& )
962 : {
963 : // Nothing matched the path
964 : }
965 :
966 0 : if ( NULL != object.get( ) )
967 : {
968 : // Are the base type matching?
969 0 : if ( object->getBaseType( ) != m_pObjectType->getBaseType( )->getId() )
970 : {
971 : ucbhelper::cancelCommandExecution( uno::makeAny
972 : ( uno::RuntimeException( "Can't change a folder into a document and vice-versa.",
973 : static_cast< cppu::OWeakObject * >( this ) ) ),
974 0 : xEnv );
975 : }
976 :
977 : // Update the existing object if it's a document
978 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( object.get( ) );
979 0 : if ( NULL != document )
980 : {
981 0 : boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) );
982 0 : uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut );
983 0 : copyData( xInputStream, xOutput );
984 0 : document->setContentStream( pOut, OUSTR_TO_STDSTR( rMimeType ), string( ), bReplaceExisting );
985 : }
986 : }
987 : else
988 : {
989 : // We need to create a brand new object... either folder or document
990 0 : bool bIsFolder = getObjectType( xEnv )->getBaseType( )->getId( ) == "cmis:folder";
991 0 : setCmisProperty( "cmis:objectTypeId", getObjectType( xEnv )->getId( ), xEnv );
992 :
993 0 : if ( bIsFolder )
994 : {
995 0 : libcmis::FolderPtr pNew = pFolder->createFolder( m_pObjectProps );
996 0 : sNewPath = STD_TO_OUSTR( newPath );
997 : }
998 : else
999 : {
1000 0 : boost::shared_ptr< ostream > pOut( new ostringstream ( ios_base::binary | ios_base::in | ios_base::out ) );
1001 0 : uno::Reference < io::XOutputStream > xOutput = new ucbhelper::StdOutputStream( pOut );
1002 0 : copyData( xInputStream, xOutput );
1003 0 : pFolder->createDocument( m_pObjectProps, pOut, OUSTR_TO_STDSTR( rMimeType ), string() );
1004 0 : sNewPath = STD_TO_OUSTR( newPath );
1005 : }
1006 : }
1007 :
1008 0 : if ( !sNewPath.isEmpty( ) )
1009 : {
1010 : // Update the current content: it's no longer transient
1011 0 : m_sObjectPath = sNewPath;
1012 0 : URL aUrl( m_sURL );
1013 0 : aUrl.setObjectPath( m_sObjectPath );
1014 0 : m_sURL = aUrl.asString( );
1015 0 : m_pObject.reset( );
1016 0 : m_pObjectType.reset( );
1017 0 : m_pObjectProps.clear( );
1018 0 : m_bTransient = false;
1019 :
1020 0 : inserted();
1021 0 : }
1022 0 : }
1023 : }
1024 0 : }
1025 :
1026 : const int TRANSFER_BUFFER_SIZE = 65536;
1027 :
1028 0 : void Content::copyData(
1029 : uno::Reference< io::XInputStream > xIn,
1030 : uno::Reference< io::XOutputStream > xOut )
1031 : {
1032 0 : uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
1033 :
1034 0 : while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
1035 0 : xOut->writeBytes( theData );
1036 :
1037 0 : xOut->closeOutput();
1038 0 : }
1039 :
1040 0 : uno::Sequence< uno::Any > Content::setPropertyValues(
1041 : const uno::Sequence< beans::PropertyValue >& rValues,
1042 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1043 : {
1044 : try
1045 : {
1046 : // Get the already set properties if possible
1047 0 : if ( !m_bTransient && getObject( xEnv ).get( ) )
1048 : {
1049 0 : m_pObjectProps.clear( );
1050 0 : m_pObjectType = getObject( xEnv )->getTypeDescription();
1051 : }
1052 : }
1053 0 : catch ( const libcmis::Exception& e )
1054 : {
1055 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
1056 : ucbhelper::cancelCommandExecution(
1057 : ucb::IOErrorCode_GENERAL,
1058 : uno::Sequence< uno::Any >( 0 ),
1059 : xEnv,
1060 0 : rtl::OUString::createFromAscii( e.what() ) );
1061 : }
1062 :
1063 0 : sal_Int32 nCount = rValues.getLength();
1064 0 : uno::Sequence< uno::Any > aRet( nCount );
1065 :
1066 0 : bool bChanged = false;
1067 0 : const beans::PropertyValue* pValues = rValues.getConstArray();
1068 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
1069 : {
1070 0 : const beans::PropertyValue& rValue = pValues[ n ];
1071 0 : if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
1072 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ||
1073 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
1074 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
1075 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ||
1076 0 : rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
1077 : {
1078 : lang::IllegalAccessException e ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only!")),
1079 0 : static_cast< cppu::OWeakObject* >( this ) );
1080 0 : aRet[ n ] <<= e;
1081 : }
1082 0 : else if ( rValue.Name == "Title" )
1083 : {
1084 0 : rtl::OUString aNewTitle;
1085 0 : if (!( rValue.Value >>= aNewTitle ))
1086 : {
1087 0 : aRet[ n ] <<= beans::IllegalTypeException
1088 : ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property value has wrong type!")),
1089 0 : static_cast< cppu::OWeakObject * >( this ) );
1090 0 : continue;
1091 : }
1092 :
1093 0 : if ( aNewTitle.getLength() <= 0 )
1094 : {
1095 0 : aRet[ n ] <<= lang::IllegalArgumentException
1096 : ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Empty title not allowed!")),
1097 0 : static_cast< cppu::OWeakObject * >( this ), -1 );
1098 0 : continue;
1099 :
1100 : }
1101 :
1102 0 : setCmisProperty( "cmis:name", OUSTR_TO_STDSTR( aNewTitle ), xEnv );
1103 0 : bChanged = true;
1104 : }
1105 : else
1106 : {
1107 : SAL_INFO( "cmisucp", "Couln't set property: " << rValue.Name );
1108 : lang::IllegalAccessException e ( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Property is read-only!")),
1109 0 : static_cast< cppu::OWeakObject* >( this ) );
1110 0 : aRet[ n ] <<= e;
1111 : }
1112 : }
1113 :
1114 : try
1115 : {
1116 0 : if ( !m_bTransient && bChanged )
1117 : {
1118 0 : getObject( xEnv )->updateProperties( m_pObjectProps );
1119 : }
1120 : }
1121 0 : catch ( const libcmis::Exception& e )
1122 : {
1123 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
1124 : ucbhelper::cancelCommandExecution(
1125 : ucb::IOErrorCode_GENERAL,
1126 : uno::Sequence< uno::Any >( 0 ),
1127 : xEnv,
1128 0 : rtl::OUString::createFromAscii( e.what() ) );
1129 : }
1130 :
1131 0 : return aRet;
1132 : }
1133 :
1134 0 : sal_Bool Content::feedSink( uno::Reference< uno::XInterface> xSink,
1135 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1136 : {
1137 0 : if ( !xSink.is() )
1138 0 : return sal_False;
1139 :
1140 0 : uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY );
1141 0 : uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY );
1142 0 : uno::Reference< io::XActiveDataStreamer > xDataStreamer = uno::Reference< io::XActiveDataStreamer >( xSink, uno::UNO_QUERY );
1143 :
1144 0 : if ( !xOut.is() && !xDataSink.is() && ( !xDataStreamer.is() || !xDataStreamer->getStream().is() ) )
1145 0 : return sal_False;
1146 :
1147 0 : if ( xDataStreamer.is() && !xOut.is() )
1148 0 : xOut = xDataStreamer->getStream()->getOutputStream();
1149 :
1150 : try
1151 : {
1152 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( getObject( xEnv ).get() );
1153 0 : boost::shared_ptr< istream > aIn = document->getContentStream( );
1154 :
1155 0 : uno::Reference< io::XInputStream > xIn = new ucbhelper::StdInputStream( aIn );
1156 0 : if( !xIn.is( ) )
1157 0 : return sal_False;
1158 :
1159 0 : if ( xDataSink.is() )
1160 0 : xDataSink->setInputStream( xIn );
1161 0 : else if ( xOut.is() )
1162 0 : copyData( xIn, xOut );
1163 : }
1164 0 : catch ( const libcmis::Exception& e )
1165 : {
1166 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
1167 : ucbhelper::cancelCommandExecution(
1168 : ucb::IOErrorCode_GENERAL,
1169 : uno::Sequence< uno::Any >( 0 ),
1170 : xEnv,
1171 0 : rtl::OUString::createFromAscii( e.what() ) );
1172 : }
1173 :
1174 0 : return sal_True;
1175 : }
1176 :
1177 0 : uno::Sequence< beans::Property > Content::getProperties(
1178 : const uno::Reference< ucb::XCommandEnvironment > & )
1179 : {
1180 : static const beans::Property aGenericProperties[] =
1181 : {
1182 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
1183 0 : -1, getCppuBooleanType(),
1184 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1185 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
1186 0 : -1, getCppuBooleanType(),
1187 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1188 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
1189 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1190 : beans::PropertyAttribute::BOUND ),
1191 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "TitleOnServer" ) ),
1192 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1193 : beans::PropertyAttribute::BOUND ),
1194 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
1195 0 : -1, getCppuBooleanType(),
1196 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1197 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
1198 0 : -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
1199 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1200 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
1201 0 : -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
1202 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1203 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
1204 0 : -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
1205 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1206 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CreatableContentsInfo" ) ),
1207 0 : -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1208 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1209 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1210 0 : -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1211 : beans::PropertyAttribute::BOUND ),
1212 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CmisPropertiesValues" ) ),
1213 0 : -1, getCppuType( static_cast< const beans::PropertyValues * >( 0 ) ),
1214 : beans::PropertyAttribute::BOUND ),
1215 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CmisPropertiesDisplayNames" ) ),
1216 0 : -1, getCppuType( static_cast< const beans::PropertyValues * >( 0 ) ),
1217 : beans::PropertyAttribute::BOUND ),
1218 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVersionable" ) ),
1219 0 : -1, getCppuBooleanType(),
1220 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1221 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCheckOut" ) ),
1222 0 : -1, getCppuBooleanType(),
1223 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1224 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCancelCheckOut" ) ),
1225 0 : -1, getCppuBooleanType(),
1226 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1227 : beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CanCheckIn" ) ),
1228 0 : -1, getCppuBooleanType(),
1229 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1230 0 : };
1231 :
1232 0 : const int nProps = SAL_N_ELEMENTS(aGenericProperties);
1233 0 : return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
1234 : }
1235 :
1236 0 : uno::Sequence< ucb::CommandInfo > Content::getCommands(
1237 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1238 : {
1239 : static ucb::CommandInfo aCommandInfoTable[] =
1240 : {
1241 : // Required commands
1242 : ucb::CommandInfo
1243 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
1244 0 : -1, getCppuVoidType() ),
1245 : ucb::CommandInfo
1246 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
1247 0 : -1, getCppuVoidType() ),
1248 : ucb::CommandInfo
1249 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
1250 0 : -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
1251 : ucb::CommandInfo
1252 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
1253 0 : -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
1254 :
1255 : // Optional standard commands
1256 : ucb::CommandInfo
1257 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
1258 0 : -1, getCppuBooleanType() ),
1259 : ucb::CommandInfo
1260 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1261 0 : -1, getCppuType( static_cast<ucb::InsertCommandArgument2 * >( 0 ) ) ),
1262 : ucb::CommandInfo
1263 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
1264 0 : -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ),
1265 :
1266 : // Mandatory CMIS-only commands
1267 0 : ucb::CommandInfo ( rtl::OUString( "checkout" ), -1, getCppuVoidType() ),
1268 0 : ucb::CommandInfo ( rtl::OUString( "cancelCheckout" ), -1, getCppuVoidType() ),
1269 : ucb::CommandInfo ( rtl::OUString( "checkIn" ), -1,
1270 0 : getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ),
1271 :
1272 : // Folder Only, omitted if not a folder
1273 : ucb::CommandInfo
1274 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
1275 0 : -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ),
1276 : ucb::CommandInfo
1277 : ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "createNewContent" ) ),
1278 0 : -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) )
1279 0 : };
1280 :
1281 0 : const int nProps = SAL_N_ELEMENTS( aCommandInfoTable );
1282 0 : return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder( xEnv ) ? nProps : nProps - 2);
1283 : }
1284 :
1285 0 : ::rtl::OUString Content::getParentURL( )
1286 : {
1287 0 : rtl::OUString sRet;
1288 :
1289 : SAL_INFO( "cmisucp", "Content::getParentURL()" );
1290 :
1291 0 : string parentPath;
1292 : try
1293 : {
1294 0 : libcmis::ObjectPtr pObj = getObject( uno::Reference< ucb::XCommandEnvironment >() );
1295 0 : libcmis::Document* document = dynamic_cast< libcmis::Document* >( pObj.get( ) );
1296 0 : if ( NULL != document )
1297 : {
1298 0 : vector< boost::shared_ptr< libcmis::Folder > > parents = document->getParents( );
1299 0 : if ( !parents.empty( ) )
1300 0 : parentPath = parents.front( )->getPath( );
1301 : }
1302 : else
1303 : {
1304 0 : libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( pObj.get( ) );
1305 0 : if ( NULL != folder )
1306 0 : parentPath = folder->getFolderParent( )->getPath( );
1307 0 : }
1308 : }
1309 0 : catch ( const libcmis::Exception & )
1310 : {
1311 : // We may have an exception if we don't have the rights to
1312 : // get the parents
1313 : }
1314 :
1315 0 : if ( !parentPath.empty() )
1316 : {
1317 0 : URL aUrl( m_sURL );
1318 0 : aUrl.setObjectPath( STD_TO_OUSTR( parentPath ) );
1319 0 : sRet = aUrl.asString( );
1320 : }
1321 : else
1322 : {
1323 0 : INetURLObject aUrl( m_sURL );
1324 0 : if ( aUrl.getSegmentCount( ) > 0 )
1325 : {
1326 0 : URL aCmisUrl( m_sURL );
1327 0 : aUrl.removeSegment( );
1328 0 : aCmisUrl.setObjectPath( aUrl.GetURLPath( INetURLObject::NO_DECODE ) );
1329 0 : sRet = aCmisUrl.asString( );
1330 0 : }
1331 : }
1332 :
1333 0 : return sRet;
1334 : }
1335 :
1336 0 : XTYPEPROVIDER_COMMON_IMPL( Content );
1337 :
1338 0 : void SAL_CALL Content::acquire() throw()
1339 : {
1340 0 : ContentImplHelper::acquire();
1341 0 : }
1342 :
1343 0 : void SAL_CALL Content::release() throw()
1344 : {
1345 0 : ContentImplHelper::release();
1346 0 : }
1347 :
1348 0 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException )
1349 : {
1350 0 : uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) );
1351 0 : return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType);
1352 : }
1353 :
1354 0 : rtl::OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException )
1355 : {
1356 0 : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.CmisContent"));
1357 : }
1358 :
1359 0 : uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
1360 : throw( uno::RuntimeException )
1361 : {
1362 0 : uno::Sequence< rtl::OUString > aSNS( 1 );
1363 0 : aSNS.getArray()[ 0 ] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.CmisContent"));
1364 0 : return aSNS;
1365 : }
1366 :
1367 0 : rtl::OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException )
1368 : {
1369 0 : return isFolder( uno::Reference< ucb::XCommandEnvironment >() )
1370 : ? rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FOLDER_TYPE ))
1371 0 : : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FILE_TYPE ));
1372 : }
1373 :
1374 0 : uno::Any SAL_CALL Content::execute(
1375 : const ucb::Command& aCommand,
1376 : sal_Int32 /*CommandId*/,
1377 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1378 : throw( uno::Exception, ucb::CommandAbortedException, uno::RuntimeException )
1379 : {
1380 : SAL_INFO( "cmisucp", "Content::execute( ) - " << aCommand.Name );
1381 0 : uno::Any aRet;
1382 :
1383 0 : if ( aCommand.Name == "getPropertyValues" )
1384 : {
1385 0 : uno::Sequence< beans::Property > Properties;
1386 0 : if ( !( aCommand.Argument >>= Properties ) )
1387 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1388 0 : aRet <<= getPropertyValues( Properties, xEnv );
1389 : }
1390 0 : else if ( aCommand.Name == "getPropertySetInfo" )
1391 0 : aRet <<= getPropertySetInfo( xEnv, sal_False );
1392 0 : else if ( aCommand.Name == "getCommandInfo" )
1393 0 : aRet <<= getCommandInfo( xEnv, sal_False );
1394 0 : else if ( aCommand.Name == "open" )
1395 : {
1396 0 : ucb::OpenCommandArgument2 aOpenCommand;
1397 0 : if ( !( aCommand.Argument >>= aOpenCommand ) )
1398 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1399 0 : aRet = open( aOpenCommand, xEnv );
1400 : }
1401 0 : else if ( aCommand.Name == "transfer" )
1402 : {
1403 0 : ucb::TransferInfo transferArgs;
1404 0 : if ( !( aCommand.Argument >>= transferArgs ) )
1405 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1406 0 : transfer( transferArgs, xEnv );
1407 : }
1408 0 : else if ( aCommand.Name == "setPropertyValues" )
1409 : {
1410 0 : uno::Sequence< beans::PropertyValue > aProperties;
1411 0 : if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() )
1412 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1413 0 : aRet <<= setPropertyValues( aProperties, xEnv );
1414 : }
1415 0 : else if (aCommand.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) )
1416 0 : && isFolder( xEnv ) )
1417 : {
1418 0 : ucb::ContentInfo arg;
1419 0 : if ( !( aCommand.Argument >>= arg ) )
1420 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1421 0 : aRet <<= createNewContent( arg );
1422 : }
1423 0 : else if ( aCommand.Name == "insert" )
1424 : {
1425 0 : ucb::InsertCommandArgument2 arg;
1426 0 : if ( !( aCommand.Argument >>= arg ) )
1427 : {
1428 0 : ucb::InsertCommandArgument insertArg;
1429 0 : if ( !( aCommand.Argument >>= insertArg ) )
1430 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
1431 :
1432 0 : arg.Data = insertArg.Data;
1433 0 : arg.ReplaceExisting = insertArg.ReplaceExisting;
1434 : }
1435 0 : insert( arg.Data, arg.ReplaceExisting, arg.MimeType, xEnv );
1436 : }
1437 0 : else if ( aCommand.Name == "delete" )
1438 : {
1439 : try
1440 : {
1441 0 : if ( !isFolder( xEnv ) )
1442 : {
1443 0 : getObject( xEnv )->remove( );
1444 : }
1445 : else
1446 : {
1447 0 : libcmis::Folder* folder = dynamic_cast< libcmis::Folder* >( getObject( xEnv ).get() );
1448 0 : folder->removeTree( );
1449 : }
1450 : }
1451 0 : catch ( const libcmis::Exception& e )
1452 : {
1453 : SAL_INFO( "cmisucp", "Unexpected libcmis exception: " << e.what( ) );
1454 : ucbhelper::cancelCommandExecution(
1455 : ucb::IOErrorCode_GENERAL,
1456 : uno::Sequence< uno::Any >( 0 ),
1457 : xEnv,
1458 0 : rtl::OUString::createFromAscii( e.what() ) );
1459 : }
1460 : }
1461 0 : else if ( aCommand.Name == "checkout" )
1462 : {
1463 0 : aRet <<= checkOut( xEnv );
1464 : }
1465 0 : else if ( aCommand.Name == "cancelCheckout" )
1466 : {
1467 0 : aRet <<= cancelCheckOut( xEnv );
1468 : }
1469 0 : else if ( aCommand.Name == "checkin" )
1470 : {
1471 0 : ucb::CheckinArgument aArg;
1472 0 : if ( !( aCommand.Argument >>= aArg ) )
1473 : {
1474 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept(), xEnv );
1475 : }
1476 0 : aRet <<= checkIn( aArg, xEnv );
1477 : }
1478 : else
1479 : {
1480 : SAL_INFO( "cmisucp", "Unknown command to execute" );
1481 :
1482 : ucbhelper::cancelCommandExecution
1483 : ( uno::makeAny( ucb::UnsupportedCommandException
1484 : ( rtl::OUString(),
1485 : static_cast< cppu::OWeakObject * >( this ) ) ),
1486 0 : xEnv );
1487 : }
1488 :
1489 0 : return aRet;
1490 : }
1491 :
1492 0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ ) throw( uno::RuntimeException )
1493 : {
1494 : SAL_INFO( "cmisucp", "TODO - Content::abort()" );
1495 : // TODO Implement me
1496 0 : }
1497 :
1498 0 : uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo()
1499 : throw( uno::RuntimeException )
1500 : {
1501 0 : return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() );
1502 : }
1503 :
1504 0 : uno::Reference< ucb::XContent > SAL_CALL Content::createNewContent(
1505 : const ucb::ContentInfo& Info ) throw( uno::RuntimeException )
1506 : {
1507 : bool create_document;
1508 :
1509 0 : if ( Info.Type == CMIS_FILE_TYPE )
1510 0 : create_document = true;
1511 0 : else if ( Info.Type == CMIS_FOLDER_TYPE )
1512 0 : create_document = false;
1513 : else
1514 : {
1515 : SAL_INFO( "cmisucp", "Unknown type of content to create" );
1516 0 : return uno::Reference< ucb::XContent >();
1517 : }
1518 :
1519 0 : rtl::OUString sParentURL = m_xIdentifier->getContentIdentifier();
1520 0 : URL aParentURL( sParentURL );
1521 :
1522 : // Set the parent URL for the transient objects
1523 0 : uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(sParentURL));
1524 :
1525 : try
1526 : {
1527 0 : return new ::cmis::Content( m_xContext, m_pProvider, xId, !create_document );
1528 : }
1529 0 : catch ( ucb::ContentCreationException & )
1530 : {
1531 0 : return uno::Reference< ucb::XContent >();
1532 0 : }
1533 : }
1534 :
1535 0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes() throw( uno::RuntimeException )
1536 : {
1537 0 : if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
1538 : {
1539 : static cppu::OTypeCollection aFolderCollection
1540 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1541 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1542 0 : CPPU_TYPE_REF( lang::XComponent ),
1543 0 : CPPU_TYPE_REF( ucb::XContent ),
1544 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1545 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1546 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1547 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1548 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1549 0 : CPPU_TYPE_REF( container::XChild ),
1550 0 : CPPU_TYPE_REF( ucb::XContentCreator ) );
1551 0 : return aFolderCollection.getTypes();
1552 : }
1553 : else
1554 : {
1555 : static cppu::OTypeCollection aFileCollection
1556 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1557 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1558 0 : CPPU_TYPE_REF( lang::XComponent ),
1559 0 : CPPU_TYPE_REF( ucb::XContent ),
1560 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1561 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1562 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1563 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1564 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1565 0 : CPPU_TYPE_REF( container::XChild ) );
1566 :
1567 0 : return aFileCollection.getTypes();
1568 : }
1569 : }
1570 :
1571 :
1572 0 : uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo(
1573 : const uno::Reference< ucb::XCommandEnvironment >& xEnv)
1574 : throw( uno::RuntimeException )
1575 : {
1576 0 : if ( isFolder( xEnv ) )
1577 : {
1578 0 : uno::Sequence< ucb::ContentInfo > seq(2);
1579 :
1580 : // Minimum set of props we really need
1581 0 : uno::Sequence< beans::Property > props( 1 );
1582 0 : props[0] = beans::Property(
1583 : rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title")),
1584 : -1,
1585 0 : getCppuType( static_cast< rtl::OUString* >( 0 ) ),
1586 0 : beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
1587 :
1588 : // file
1589 0 : seq[0].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FILE_TYPE ));
1590 0 : seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
1591 0 : ucb::ContentInfoAttribute::KIND_DOCUMENT );
1592 0 : seq[0].Properties = props;
1593 :
1594 : // folder
1595 0 : seq[1].Type = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( CMIS_FOLDER_TYPE ));
1596 0 : seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1597 0 : seq[1].Properties = props;
1598 :
1599 0 : return seq;
1600 : }
1601 : else
1602 : {
1603 0 : return uno::Sequence< ucb::ContentInfo >();
1604 : }
1605 : }
1606 :
1607 0 : list< uno::Reference< ucb::XContent > > Content::getChildren( )
1608 : {
1609 0 : list< uno::Reference< ucb::XContent > > results;
1610 : SAL_INFO( "cmisucp", "Content::getChildren() " << m_sURL );
1611 :
1612 0 : libcmis::Folder* pFolder = dynamic_cast< libcmis::Folder* >( getObject( uno::Reference< ucb::XCommandEnvironment >() ).get( ) );
1613 0 : if ( NULL != pFolder )
1614 : {
1615 : // Get the children from pObject
1616 : try
1617 : {
1618 0 : vector< libcmis::ObjectPtr > children = pFolder->getChildren( );
1619 :
1620 : // Loop over the results
1621 0 : for ( vector< libcmis::ObjectPtr >::iterator it = children.begin();
1622 0 : it != children.end(); ++it )
1623 : {
1624 : // TODO Cache the objects
1625 :
1626 0 : URL aUrl( m_sURL );
1627 0 : rtl::OUString sPath( m_sObjectPath );
1628 0 : if ( sPath[sPath.getLength( ) - 1] != '/' )
1629 0 : sPath += "/";
1630 0 : sPath += STD_TO_OUSTR( ( *it )->getName( ) );
1631 0 : aUrl.setObjectPath( sPath );
1632 0 : uno::Reference< ucb::XContentIdentifier > xId = new ucbhelper::ContentIdentifier( aUrl.asString( ) );
1633 0 : uno::Reference< ucb::XContent > xContent = new Content( m_xContext, m_pProvider, xId, *it );
1634 :
1635 0 : results.push_back( xContent );
1636 0 : }
1637 : }
1638 0 : catch ( const libcmis::Exception& e )
1639 : {
1640 : SAL_INFO( "cmisucp", "Exception thrown: " << e.what() );
1641 : }
1642 : }
1643 :
1644 0 : return results;
1645 : }
1646 :
1647 0 : void Content::setCmisProperty( std::string sName, std::string sValue, const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1648 : {
1649 0 : if ( getObjectType( xEnv ).get( ) )
1650 : {
1651 0 : map< string, libcmis::PropertyPtr >::iterator propIt = m_pObjectProps.find( sName );
1652 0 : vector< string > values;
1653 0 : values.push_back( sValue );
1654 :
1655 0 : if ( propIt == m_pObjectProps.end( ) && getObjectType( xEnv ).get( ) )
1656 : {
1657 0 : map< string, libcmis::PropertyTypePtr > propsTypes = getObjectType( xEnv )->getPropertiesTypes( );
1658 0 : map< string, libcmis::PropertyTypePtr >::iterator typeIt = propsTypes.find( sName );
1659 :
1660 0 : if ( typeIt != propsTypes.end( ) )
1661 : {
1662 0 : libcmis::PropertyTypePtr propType = typeIt->second;
1663 0 : libcmis::PropertyPtr property( new libcmis::Property( propType, values ) );
1664 0 : m_pObjectProps.insert( pair< string, libcmis::PropertyPtr >( sName, property ) );
1665 0 : }
1666 : }
1667 0 : else if ( propIt != m_pObjectProps.end( ) )
1668 : {
1669 0 : propIt->second->setValues( values );
1670 0 : }
1671 : }
1672 0 : }
1673 0 : }
1674 :
1675 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|