1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_tdoc.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32
33 #include "osl/diagnose.h"
34 #include "osl/doublecheckedlocking.h"
35 #include "rtl/ustrbuf.hxx"
36
37 #include "com/sun/star/beans/PropertyAttribute.hpp"
38 #include "com/sun/star/beans/PropertyValue.hpp"
39 #include "com/sun/star/beans/XPropertySet.hpp"
40 #include "com/sun/star/embed/ElementModes.hpp"
41 #include "com/sun/star/embed/XStorage.hpp"
42 #include "com/sun/star/embed/XTransactedObject.hpp"
43 #include "com/sun/star/io/XActiveDataSink.hpp"
44 #include "com/sun/star/io/XActiveDataStreamer.hpp"
45 #include "com/sun/star/lang/IllegalAccessException.hpp"
46 #include "com/sun/star/sdbc/XRow.hpp"
47 #include "com/sun/star/ucb/ContentAction.hpp"
48 #include "com/sun/star/ucb/ContentInfoAttribute.hpp"
49 #include "com/sun/star/ucb/InsertCommandArgument.hpp"
50 #include "com/sun/star/ucb/InteractiveBadTransferURLException.hpp"
51 #include "com/sun/star/ucb/MissingInputStreamException.hpp"
52 #include "com/sun/star/ucb/MissingPropertiesException.hpp"
53 #include "com/sun/star/ucb/NameClash.hpp"
54 #include "com/sun/star/ucb/NameClashException.hpp"
55 #include "com/sun/star/ucb/OpenCommandArgument2.hpp"
56 #include "com/sun/star/ucb/OpenMode.hpp"
57 #include "com/sun/star/ucb/TransferInfo.hpp"
58 #include "com/sun/star/ucb/UnsupportedCommandException.hpp"
59 #include "com/sun/star/ucb/UnsupportedDataSinkException.hpp"
60 #include "com/sun/star/ucb/UnsupportedNameClashException.hpp"
61 #include "com/sun/star/ucb/UnsupportedOpenModeException.hpp"
62 #include "com/sun/star/ucb/XCommandInfo.hpp"
63 #include "com/sun/star/ucb/XPersistentPropertySet.hpp"
64
65 #include "ucbhelper/cancelcommandexecution.hxx"
66 #include "ucbhelper/contentidentifier.hxx"
67 #include "ucbhelper/propertyvalueset.hxx"
68
69 #include "tdoc_content.hxx"
70 #include "tdoc_resultset.hxx"
71 #include "tdoc_passwordrequest.hxx"
72
73 #include "../inc/urihelper.hxx"
74
75 using namespace com::sun::star;
76 using namespace tdoc_ucp;
77
78 //=========================================================================
lcl_getContentType(const rtl::OUString & rType)79 static ContentType lcl_getContentType( const rtl::OUString & rType )
80 {
81 if ( rType.equalsAsciiL(
82 RTL_CONSTASCII_STRINGPARAM( TDOC_ROOT_CONTENT_TYPE ) ) )
83 return ROOT;
84 else if ( rType.equalsAsciiL(
85 RTL_CONSTASCII_STRINGPARAM( TDOC_DOCUMENT_CONTENT_TYPE ) ) )
86 return DOCUMENT;
87 else if ( rType.equalsAsciiL(
88 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) )
89 return FOLDER;
90 else if ( rType.equalsAsciiL(
91 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) )
92 return STREAM;
93 else
94 {
95 OSL_ENSURE( sal_False,
96 "Content::Content - unsupported content type string" );
97 return STREAM;
98 }
99 }
100
101 //=========================================================================
102 //=========================================================================
103 //
104 // Content Implementation.
105 //
106 //=========================================================================
107 //=========================================================================
108
109 // static ( "virtual" ctor )
create(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,ContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier)110 Content* Content::create(
111 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
112 ContentProvider* pProvider,
113 const uno::Reference< ucb::XContentIdentifier >& Identifier )
114 {
115 // Fail, if resource does not exist.
116 ContentProperties aProps;
117 if ( !Content::loadData( pProvider,
118 Uri( Identifier->getContentIdentifier() ),
119 aProps ) )
120 return 0;
121
122 return new Content( rxSMgr, pProvider, Identifier, aProps );
123 }
124
125 //=========================================================================
126 // static ( "virtual" ctor )
create(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,ContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const ucb::ContentInfo & Info)127 Content* Content::create(
128 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
129 ContentProvider* pProvider,
130 const uno::Reference< ucb::XContentIdentifier >& Identifier,
131 const ucb::ContentInfo& Info )
132 {
133 if ( !Info.Type.getLength() )
134 return 0;
135
136 if ( !Info.Type.equalsAsciiL(
137 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) ) &&
138 !Info.Type.equalsAsciiL(
139 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) )
140 {
141 OSL_ENSURE( sal_False, "Content::create - unsupported content type!" );
142 return 0;
143 }
144
145 #if 0
146 // Fail, if content does exist.
147 if ( Content::hasData( pProvider,
148 Uri( Identifier->getContentIdentifier() ) ) )
149 return 0;
150 #endif
151
152 return new Content( rxSMgr, pProvider, Identifier, Info );
153 }
154
155 //=========================================================================
Content(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,ContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const ContentProperties & rProps)156 Content::Content(
157 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr,
158 ContentProvider * pProvider,
159 const uno::Reference< ucb::XContentIdentifier > & Identifier,
160 const ContentProperties & rProps )
161 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
162 m_aProps( rProps ),
163 m_eState( PERSISTENT ),
164 m_pProvider( pProvider )
165 {
166 }
167
168 //=========================================================================
169 // ctor for a content just created via XContentCreator::createNewContent()
Content(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,ContentProvider * pProvider,const uno::Reference<ucb::XContentIdentifier> & Identifier,const ucb::ContentInfo & Info)170 Content::Content(
171 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
172 ContentProvider* pProvider,
173 const uno::Reference< ucb::XContentIdentifier >& Identifier,
174 const ucb::ContentInfo& Info )
175 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
176 m_aProps( lcl_getContentType( Info.Type ), rtl::OUString() ), // no Title (yet)
177 m_eState( TRANSIENT ),
178 m_pProvider( pProvider )
179 {
180 }
181
182 //=========================================================================
183 // virtual
~Content()184 Content::~Content()
185 {
186 }
187
188 //=========================================================================
189 //
190 // XInterface methods.
191 //
192 //=========================================================================
193
194 // virtual
acquire()195 void SAL_CALL Content::acquire()
196 throw( )
197 {
198 ContentImplHelper::acquire();
199 }
200
201 //=========================================================================
202 // virtual
release()203 void SAL_CALL Content::release()
204 throw( )
205 {
206 ContentImplHelper::release();
207 }
208
209 //=========================================================================
210 // virtual
queryInterface(const uno::Type & rType)211 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
212 throw ( uno::RuntimeException )
213 {
214 uno::Any aRet = ContentImplHelper::queryInterface( rType );
215
216 if ( !aRet.hasValue() )
217 {
218 aRet = cppu::queryInterface(
219 rType, static_cast< ucb::XContentCreator * >( this ) );
220 if ( aRet.hasValue() )
221 {
222 if ( !m_aProps.isContentCreator() )
223 return uno::Any();
224 }
225 }
226
227 return aRet;
228 }
229
230 //=========================================================================
231 //
232 // XTypeProvider methods.
233 //
234 //=========================================================================
235
236 XTYPEPROVIDER_COMMON_IMPL( Content );
237
238 //=========================================================================
239 // virtual
getTypes()240 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
241 throw( uno::RuntimeException )
242 {
243 cppu::OTypeCollection * pCollection = 0;
244
245 if ( m_aProps.isContentCreator() )
246 {
247 static cppu::OTypeCollection* pFolderTypes = 0;
248
249 pCollection = pFolderTypes;
250 if ( !pCollection )
251 {
252 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
253
254 pCollection = pFolderTypes;
255 if ( !pCollection )
256 {
257 static cppu::OTypeCollection aCollection(
258 CPPU_TYPE_REF( lang::XTypeProvider ),
259 CPPU_TYPE_REF( lang::XServiceInfo ),
260 CPPU_TYPE_REF( lang::XComponent ),
261 CPPU_TYPE_REF( ucb::XContent ),
262 CPPU_TYPE_REF( ucb::XCommandProcessor ),
263 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
264 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
265 CPPU_TYPE_REF( beans::XPropertyContainer ),
266 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
267 CPPU_TYPE_REF( container::XChild ),
268 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
269 pCollection = &aCollection;
270 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
271 pFolderTypes = pCollection;
272 }
273 }
274 else {
275 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
276 }
277 }
278 else
279 {
280 static cppu::OTypeCollection* pDocumentTypes = 0;
281
282 pCollection = pDocumentTypes;
283 if ( !pCollection )
284 {
285 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
286
287 pCollection = pDocumentTypes;
288 if ( !pCollection )
289 {
290 static cppu::OTypeCollection aCollection(
291 CPPU_TYPE_REF( lang::XTypeProvider ),
292 CPPU_TYPE_REF( lang::XServiceInfo ),
293 CPPU_TYPE_REF( lang::XComponent ),
294 CPPU_TYPE_REF( ucb::XContent ),
295 CPPU_TYPE_REF( ucb::XCommandProcessor ),
296 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
297 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
298 CPPU_TYPE_REF( beans::XPropertyContainer ),
299 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
300 CPPU_TYPE_REF( container::XChild ) );
301 pCollection = &aCollection;
302 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
303 pDocumentTypes = pCollection;
304 }
305 }
306 else {
307 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
308 }
309 }
310
311 return (*pCollection).getTypes();
312 }
313
314 //=========================================================================
315 //
316 // XServiceInfo methods.
317 //
318 //=========================================================================
319
320 // virtual
getImplementationName()321 rtl::OUString SAL_CALL Content::getImplementationName()
322 throw( uno::RuntimeException )
323 {
324 return rtl::OUString::createFromAscii(
325 "com.sun.star.comp.ucb.TransientDocumentsContent" );
326 }
327
328 //=========================================================================
329 // virtual
getSupportedServiceNames()330 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
331 throw( uno::RuntimeException )
332 {
333 osl::Guard< osl::Mutex > aGuard( m_aMutex );
334
335 uno::Sequence< rtl::OUString > aSNS( 1 );
336
337 if ( m_aProps.getType() == STREAM )
338 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
339 TDOC_STREAM_CONTENT_SERVICE_NAME );
340 else if ( m_aProps.getType() == FOLDER )
341 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
342 TDOC_FOLDER_CONTENT_SERVICE_NAME );
343 else if ( m_aProps.getType() == DOCUMENT )
344 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
345 TDOC_DOCUMENT_CONTENT_SERVICE_NAME );
346 else
347 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
348 TDOC_ROOT_CONTENT_SERVICE_NAME );
349
350 return aSNS;
351 }
352
353 //=========================================================================
354 //
355 // XContent methods.
356 //
357 //=========================================================================
358
359 // virtual
getContentType()360 rtl::OUString SAL_CALL Content::getContentType()
361 throw( uno::RuntimeException )
362 {
363 osl::Guard< osl::Mutex > aGuard( m_aMutex );
364 return m_aProps.getContentType();
365 }
366
367 //=========================================================================
368 // virtual
369 uno::Reference< ucb::XContentIdentifier > SAL_CALL
getIdentifier()370 Content::getIdentifier()
371 throw( uno::RuntimeException )
372 {
373 {
374 osl::Guard< osl::Mutex > aGuard( m_aMutex );
375
376 // Transient?
377 if ( m_eState == TRANSIENT )
378 {
379 // Transient contents have no identifier.
380 return uno::Reference< ucb::XContentIdentifier >();
381 }
382 }
383 return ContentImplHelper::getIdentifier();
384 }
385
386 //=========================================================================
387 //
388 // XCommandProcessor methods.
389 //
390 //=========================================================================
391
392 // virtual
execute(const ucb::Command & aCommand,sal_Int32,const uno::Reference<ucb::XCommandEnvironment> & Environment)393 uno::Any SAL_CALL Content::execute(
394 const ucb::Command& aCommand,
395 sal_Int32 /*CommandId*/,
396 const uno::Reference< ucb::XCommandEnvironment >& Environment )
397 throw( uno::Exception,
398 ucb::CommandAbortedException,
399 uno::RuntimeException )
400 {
401 uno::Any aRet;
402
403 if ( aCommand.Name.equalsAsciiL(
404 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
405 {
406 //////////////////////////////////////////////////////////////////
407 // getPropertyValues
408 //////////////////////////////////////////////////////////////////
409
410 uno::Sequence< beans::Property > Properties;
411 if ( !( aCommand.Argument >>= Properties ) )
412 {
413 ucbhelper::cancelCommandExecution(
414 uno::makeAny( lang::IllegalArgumentException(
415 rtl::OUString::createFromAscii(
416 "Wrong argument type!" ),
417 static_cast< cppu::OWeakObject * >( this ),
418 -1 ) ),
419 Environment );
420 // Unreachable
421 }
422
423 aRet <<= getPropertyValues( Properties );
424 }
425 else if ( aCommand.Name.equalsAsciiL(
426 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
427 {
428 //////////////////////////////////////////////////////////////////
429 // setPropertyValues
430 //////////////////////////////////////////////////////////////////
431
432 uno::Sequence< beans::PropertyValue > aProperties;
433 if ( !( aCommand.Argument >>= aProperties ) )
434 {
435 ucbhelper::cancelCommandExecution(
436 uno::makeAny( lang::IllegalArgumentException(
437 rtl::OUString::createFromAscii(
438 "Wrong argument type!" ),
439 static_cast< cppu::OWeakObject * >( this ),
440 -1 ) ),
441 Environment );
442 // Unreachable
443 }
444
445 if ( !aProperties.getLength() )
446 {
447 ucbhelper::cancelCommandExecution(
448 uno::makeAny( lang::IllegalArgumentException(
449 rtl::OUString::createFromAscii(
450 "No properties!" ),
451 static_cast< cppu::OWeakObject * >( this ),
452 -1 ) ),
453 Environment );
454 // Unreachable
455 }
456
457 aRet <<= setPropertyValues( aProperties, Environment );
458 }
459 else if ( aCommand.Name.equalsAsciiL(
460 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
461 {
462 //////////////////////////////////////////////////////////////////
463 // getPropertySetInfo
464 //////////////////////////////////////////////////////////////////
465
466 aRet <<= getPropertySetInfo( Environment );
467 }
468 else if ( aCommand.Name.equalsAsciiL(
469 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
470 {
471 //////////////////////////////////////////////////////////////////
472 // getCommandInfo
473 //////////////////////////////////////////////////////////////////
474
475 aRet <<= getCommandInfo( Environment );
476 }
477 else if ( aCommand.Name.equalsAsciiL(
478 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
479 {
480 //////////////////////////////////////////////////////////////////
481 // open
482 //////////////////////////////////////////////////////////////////
483
484 ucb::OpenCommandArgument2 aOpenCommand;
485 if ( !( aCommand.Argument >>= aOpenCommand ) )
486 {
487 ucbhelper::cancelCommandExecution(
488 uno::makeAny( lang::IllegalArgumentException(
489 rtl::OUString::createFromAscii(
490 "Wrong argument type!" ),
491 static_cast< cppu::OWeakObject * >( this ),
492 -1 ) ),
493 Environment );
494 // Unreachable
495 }
496
497 aRet = open( aOpenCommand, Environment );
498 }
499 else if ( aCommand.Name.equalsAsciiL(
500 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
501 {
502 //////////////////////////////////////////////////////////////////
503 // insert ( Supported by folders and streams only )
504 //////////////////////////////////////////////////////////////////
505
506 ContentType eType = m_aProps.getType();
507 if ( ( eType != FOLDER ) && ( eType != STREAM ) )
508 {
509 ucbhelper::cancelCommandExecution(
510 uno::makeAny( ucb::UnsupportedCommandException(
511 rtl::OUString(
512 RTL_CONSTASCII_USTRINGPARAM(
513 "insert command only supported by "
514 "folders and streams!" ) ),
515 static_cast< cppu::OWeakObject * >( this ) ) ),
516 Environment );
517 // Unreachable
518 }
519
520 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
521 if ( eType == STREAM )
522 {
523 Uri aUri( m_xIdentifier->getContentIdentifier() );
524 Uri aParentUri( aUri.getParentUri() );
525 if ( aParentUri.isDocument() )
526 {
527 ucbhelper::cancelCommandExecution(
528 uno::makeAny( ucb::UnsupportedCommandException(
529 rtl::OUString(
530 RTL_CONSTASCII_USTRINGPARAM(
531 "insert command not supported by "
532 "streams that are direct children "
533 "of document root!" ) ),
534 static_cast< cppu::OWeakObject * >(
535 this ) ) ),
536 Environment );
537 // Unreachable
538 }
539 }
540 #endif
541 ucb::InsertCommandArgument aArg;
542 if ( !( aCommand.Argument >>= aArg ) )
543 {
544 ucbhelper::cancelCommandExecution(
545 uno::makeAny( lang::IllegalArgumentException(
546 rtl::OUString::createFromAscii(
547 "Wrong argument type!" ),
548 static_cast< cppu::OWeakObject * >( this ),
549 -1 ) ),
550 Environment );
551 // Unreachable
552 }
553
554 sal_Int32 nNameClash = aArg.ReplaceExisting
555 ? ucb::NameClash::OVERWRITE
556 : ucb::NameClash::ERROR;
557 insert( aArg.Data, nNameClash, Environment );
558 }
559 else if ( aCommand.Name.equalsAsciiL(
560 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
561 {
562 //////////////////////////////////////////////////////////////////
563 // delete ( Supported by folders and streams only )
564 //////////////////////////////////////////////////////////////////
565
566 {
567 osl::MutexGuard aGuard( m_aMutex );
568
569 ContentType eType = m_aProps.getType();
570 if ( ( eType != FOLDER ) && ( eType != STREAM ) )
571 {
572 ucbhelper::cancelCommandExecution(
573 uno::makeAny( ucb::UnsupportedCommandException(
574 rtl::OUString(
575 RTL_CONSTASCII_USTRINGPARAM(
576 "delete command only supported by "
577 "folders and streams!" ) ),
578 static_cast< cppu::OWeakObject * >(
579 this ) ) ),
580 Environment );
581 // Unreachable
582 }
583 }
584
585 sal_Bool bDeletePhysical = sal_False;
586 aCommand.Argument >>= bDeletePhysical;
587 destroy( bDeletePhysical, Environment );
588
589 // Remove own and all children's persistent data.
590 if ( !removeData() )
591 {
592 uno::Any aProps
593 = uno::makeAny(
594 beans::PropertyValue(
595 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
596 "Uri")),
597 -1,
598 uno::makeAny(m_xIdentifier->
599 getContentIdentifier()),
600 beans::PropertyState_DIRECT_VALUE));
601 ucbhelper::cancelCommandExecution(
602 ucb::IOErrorCode_CANT_WRITE,
603 uno::Sequence< uno::Any >(&aProps, 1),
604 Environment,
605 rtl::OUString::createFromAscii(
606 "Cannot remove persistent data!" ),
607 this );
608 // Unreachable
609 }
610
611 // Remove own and all children's Additional Core Properties.
612 removeAdditionalPropertySet( sal_True );
613 }
614 else if ( aCommand.Name.equalsAsciiL(
615 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) )
616 {
617 //////////////////////////////////////////////////////////////////
618 // transfer ( Supported by document and folders only )
619 //////////////////////////////////////////////////////////////////
620
621 {
622 osl::MutexGuard aGuard( m_aMutex );
623
624 ContentType eType = m_aProps.getType();
625 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
626 {
627 ucbhelper::cancelCommandExecution(
628 uno::makeAny( ucb::UnsupportedCommandException(
629 rtl::OUString(
630 RTL_CONSTASCII_USTRINGPARAM(
631 "transfer command only supported "
632 "by folders and documents!" ) ),
633 static_cast< cppu::OWeakObject * >(
634 this ) ) ),
635 Environment );
636 // Unreachable
637 }
638 }
639
640 ucb::TransferInfo aInfo;
641 if ( !( aCommand.Argument >>= aInfo ) )
642 {
643 OSL_ENSURE( sal_False, "Wrong argument type!" );
644 ucbhelper::cancelCommandExecution(
645 uno::makeAny( lang::IllegalArgumentException(
646 rtl::OUString::createFromAscii(
647 "Wrong argument type!" ),
648 static_cast< cppu::OWeakObject * >( this ),
649 -1 ) ),
650 Environment );
651 // Unreachable
652 }
653
654 transfer( aInfo, Environment );
655 }
656 else if ( aCommand.Name.equalsAsciiL(
657 RTL_CONSTASCII_STRINGPARAM( "createNewContent" ) ) )
658 {
659 //////////////////////////////////////////////////////////////////
660 // createNewContent ( Supported by document and folders only )
661 //////////////////////////////////////////////////////////////////
662
663 {
664 osl::MutexGuard aGuard( m_aMutex );
665
666 ContentType eType = m_aProps.getType();
667 if ( ( eType != FOLDER ) && ( eType != DOCUMENT ) )
668 {
669 ucbhelper::cancelCommandExecution(
670 uno::makeAny( ucb::UnsupportedCommandException(
671 rtl::OUString(
672 RTL_CONSTASCII_USTRINGPARAM(
673 "createNewContent command only "
674 "supported by folders and "
675 "documents!" ) ),
676 static_cast< cppu::OWeakObject * >(
677 this ) ) ),
678 Environment );
679 // Unreachable
680 }
681 }
682
683 ucb::ContentInfo aInfo;
684 if ( !( aCommand.Argument >>= aInfo ) )
685 {
686 OSL_ENSURE( sal_False, "Wrong argument type!" );
687 ucbhelper::cancelCommandExecution(
688 uno::makeAny( lang::IllegalArgumentException(
689 rtl::OUString::createFromAscii(
690 "Wrong argument type!" ),
691 static_cast< cppu::OWeakObject * >( this ),
692 -1 ) ),
693 Environment );
694 // Unreachable
695 }
696
697 aRet <<= createNewContent( aInfo );
698 }
699 else
700 {
701 //////////////////////////////////////////////////////////////////
702 // Unsupported command
703 //////////////////////////////////////////////////////////////////
704
705 ucbhelper::cancelCommandExecution(
706 uno::makeAny( ucb::UnsupportedCommandException(
707 rtl::OUString(),
708 static_cast< cppu::OWeakObject * >( this ) ) ),
709 Environment );
710 // Unreachable
711 }
712
713 return aRet;
714 }
715
716 //=========================================================================
717 // virtual
abort(sal_Int32)718 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
719 throw( uno::RuntimeException )
720 {
721 }
722
723 //=========================================================================
724 //
725 // XContentCreator methods.
726 //
727 //=========================================================================
728
729 // virtual
730 uno::Sequence< ucb::ContentInfo > SAL_CALL
queryCreatableContentsInfo()731 Content::queryCreatableContentsInfo()
732 throw( uno::RuntimeException )
733 {
734 return m_aProps.getCreatableContentsInfo();
735 }
736
737 //=========================================================================
738 // virtual
739 uno::Reference< ucb::XContent > SAL_CALL
createNewContent(const ucb::ContentInfo & Info)740 Content::createNewContent( const ucb::ContentInfo& Info )
741 throw( uno::RuntimeException )
742 {
743 if ( m_aProps.isContentCreator() )
744 {
745 osl::Guard< osl::Mutex > aGuard( m_aMutex );
746
747 if ( !Info.Type.getLength() )
748 return uno::Reference< ucb::XContent >();
749
750 sal_Bool bCreateFolder =
751 Info.Type.equalsAsciiL(
752 RTL_CONSTASCII_STRINGPARAM( TDOC_FOLDER_CONTENT_TYPE ) );
753
754 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
755 // streams cannot be created as direct children of document root
756 if ( !bCreateFolder && ( m_aProps.getType() == DOCUMENT ) )
757 {
758 OSL_ENSURE( sal_False,
759 "Content::createNewContent - streams cannot be "
760 "created as direct children of document root!" );
761 return uno::Reference< ucb::XContent >();
762 }
763 #endif
764 if ( !bCreateFolder &&
765 !Info.Type.equalsAsciiL(
766 RTL_CONSTASCII_STRINGPARAM( TDOC_STREAM_CONTENT_TYPE ) ) )
767 {
768 OSL_ENSURE( sal_False,
769 "Content::createNewContent - unsupported type!" );
770 return uno::Reference< ucb::XContent >();
771 }
772
773 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
774
775 OSL_ENSURE( aURL.getLength() > 0,
776 "Content::createNewContent - empty identifier!" );
777
778 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
779 aURL += rtl::OUString::createFromAscii( "/" );
780
781 if ( bCreateFolder )
782 aURL += rtl::OUString::createFromAscii( "New_Folder" );
783 else
784 aURL += rtl::OUString::createFromAscii( "New_Stream" );
785
786 uno::Reference< ucb::XContentIdentifier > xId
787 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL );
788
789 return create( m_xSMgr, m_pProvider, xId, Info );
790 }
791 else
792 {
793 OSL_ENSURE( sal_False,
794 "createNewContent called on non-contentcreator object!" );
795 return uno::Reference< ucb::XContent >();
796 }
797 }
798
799 //=========================================================================
800 // virtual
getParentURL()801 rtl::OUString Content::getParentURL()
802 {
803 osl::Guard< osl::Mutex > aGuard( m_aMutex );
804 Uri aUri( m_xIdentifier->getContentIdentifier() );
805 return aUri.getParentUri();
806 }
807
808 //=========================================================================
809 uno::Reference< ucb::XContentIdentifier >
makeNewIdentifier(const rtl::OUString & rTitle)810 Content::makeNewIdentifier( const rtl::OUString& rTitle )
811 {
812 osl::Guard< osl::Mutex > aGuard( m_aMutex );
813
814 // Assemble new content identifier...
815 Uri aUri( m_xIdentifier->getContentIdentifier() );
816 rtl::OUStringBuffer aNewURL = aUri.getParentUri();
817 aNewURL.append( ::ucb_impl::urihelper::encodeSegment( rTitle ) );
818
819 return
820 uno::Reference< ucb::XContentIdentifier >(
821 new ::ucbhelper::ContentIdentifier(
822 m_xSMgr, aNewURL.makeStringAndClear() ) );
823 }
824
825 //=========================================================================
queryChildren(ContentRefList & rChildren)826 void Content::queryChildren( ContentRefList& rChildren )
827 {
828 osl::Guard< osl::Mutex > aGuard( m_aMutex );
829
830 // Only folders (root, documents, folders) have children.
831 if ( !m_aProps.getIsFolder() )
832 return;
833
834 // Obtain a list with a snapshot of all currently instanciated contents
835 // from provider and extract the contents which are direct children
836 // of this content.
837
838 ::ucbhelper::ContentRefList aAllContents;
839 m_xProvider->queryExistingContents( aAllContents );
840
841 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
842 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
843
844 if ( nURLPos != ( aURL.getLength() - 1 ) )
845 {
846 // No trailing slash found. Append.
847 aURL += rtl::OUString::createFromAscii( "/" );
848 }
849
850 sal_Int32 nLen = aURL.getLength();
851
852 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
853 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
854
855 while ( it != end )
856 {
857 ::ucbhelper::ContentImplHelperRef xChild = (*it);
858 rtl::OUString aChildURL
859 = xChild->getIdentifier()->getContentIdentifier();
860
861 // Is aURL a prefix of aChildURL?
862 if ( ( aChildURL.getLength() > nLen ) &&
863 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
864 {
865 sal_Int32 nPos = nLen;
866 nPos = aChildURL.indexOf( '/', nPos );
867
868 if ( ( nPos == -1 ) ||
869 ( nPos == ( aChildURL.getLength() - 1 ) ) )
870 {
871 // No further slashes / only a final slash. It's a child!
872 rChildren.push_back(
873 ContentRef(
874 static_cast< Content * >( xChild.get() ) ) );
875 }
876 }
877 ++it;
878 }
879 }
880
881 //=========================================================================
exchangeIdentity(const uno::Reference<ucb::XContentIdentifier> & xNewId)882 sal_Bool Content::exchangeIdentity(
883 const uno::Reference< ucb::XContentIdentifier >& xNewId )
884 {
885 if ( !xNewId.is() )
886 return sal_False;
887
888 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
889
890 uno::Reference< ucb::XContent > xThis = this;
891
892 // Already persistent?
893 if ( m_eState != PERSISTENT )
894 {
895 OSL_ENSURE( sal_False,
896 "Content::exchangeIdentity - Not persistent!" );
897 return sal_False;
898 }
899
900 // Only folders and streams can be renamed -> exchange identity.
901 ContentType eType = m_aProps.getType();
902 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
903 {
904 OSL_ENSURE( sal_False, "Content::exchangeIdentity - "
905 "Not supported by root or document!" );
906 return sal_False;
907 }
908
909 // Exchange own identitity.
910
911 // Fail, if a content with given id already exists.
912 if ( !hasData( Uri( xNewId->getContentIdentifier() ) ) )
913 {
914 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
915
916 aGuard.clear();
917 if ( exchange( xNewId ) )
918 {
919 if ( eType == FOLDER )
920 {
921 // Process instanciated children...
922
923 ContentRefList aChildren;
924 queryChildren( aChildren );
925
926 ContentRefList::const_iterator it = aChildren.begin();
927 ContentRefList::const_iterator end = aChildren.end();
928
929 while ( it != end )
930 {
931 ContentRef xChild = (*it);
932
933 // Create new content identifier for the child...
934 uno::Reference< ucb::XContentIdentifier > xOldChildId
935 = xChild->getIdentifier();
936 rtl::OUString aOldChildURL
937 = xOldChildId->getContentIdentifier();
938 rtl::OUString aNewChildURL
939 = aOldChildURL.replaceAt(
940 0,
941 aOldURL.getLength(),
942 xNewId->getContentIdentifier() );
943 uno::Reference< ucb::XContentIdentifier > xNewChildId
944 = new ::ucbhelper::ContentIdentifier(
945 m_xSMgr, aNewChildURL );
946
947 if ( !xChild->exchangeIdentity( xNewChildId ) )
948 return sal_False;
949
950 ++it;
951 }
952 }
953 return sal_True;
954 }
955 }
956
957 OSL_ENSURE( sal_False,
958 "Content::exchangeIdentity - "
959 "Panic! Cannot exchange identity!" );
960 return sal_False;
961 }
962
963 //=========================================================================
964 // static
getPropertyValues(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,const uno::Sequence<beans::Property> & rProperties,ContentProvider * pProvider,const rtl::OUString & rContentId)965 uno::Reference< sdbc::XRow > Content::getPropertyValues(
966 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
967 const uno::Sequence< beans::Property >& rProperties,
968 ContentProvider* pProvider,
969 const rtl::OUString& rContentId )
970 {
971 ContentProperties aData;
972 if ( loadData( pProvider, rContentId, aData ) )
973 {
974 return getPropertyValues(
975 rSMgr, rProperties, aData, pProvider, rContentId );
976 }
977 else
978 {
979 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
980 = new ::ucbhelper::PropertyValueSet( rSMgr );
981
982 sal_Int32 nCount = rProperties.getLength();
983 if ( nCount )
984 {
985 const beans::Property* pProps = rProperties.getConstArray();
986 for ( sal_Int32 n = 0; n < nCount; ++n )
987 xRow->appendVoid( pProps[ n ] );
988 }
989
990 return uno::Reference< sdbc::XRow >( xRow.get() );
991 }
992 }
993
994 //=========================================================================
995 // static
getPropertyValues(const uno::Reference<lang::XMultiServiceFactory> & rSMgr,const uno::Sequence<beans::Property> & rProperties,const ContentProperties & rData,ContentProvider * pProvider,const rtl::OUString & rContentId)996 uno::Reference< sdbc::XRow > Content::getPropertyValues(
997 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
998 const uno::Sequence< beans::Property >& rProperties,
999 const ContentProperties& rData,
1000 ContentProvider* pProvider,
1001 const rtl::OUString& rContentId )
1002 {
1003 // Note: Empty sequence means "get values of all supported properties".
1004
1005 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
1006 = new ::ucbhelper::PropertyValueSet( rSMgr );
1007
1008 sal_Int32 nCount = rProperties.getLength();
1009 if ( nCount )
1010 {
1011 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
1012 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1013
1014 const beans::Property* pProps = rProperties.getConstArray();
1015 for ( sal_Int32 n = 0; n < nCount; ++n )
1016 {
1017 const beans::Property& rProp = pProps[ n ];
1018
1019 // Process Core properties.
1020
1021 if ( rProp.Name.equalsAsciiL(
1022 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1023 {
1024 xRow->appendString ( rProp, rData.getContentType() );
1025 }
1026 else if ( rProp.Name.equalsAsciiL(
1027 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1028 {
1029 xRow->appendString ( rProp, rData.getTitle() );
1030 }
1031 else if ( rProp.Name.equalsAsciiL(
1032 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1033 {
1034 xRow->appendBoolean( rProp, rData.getIsDocument() );
1035 }
1036 else if ( rProp.Name.equalsAsciiL(
1037 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1038 {
1039 xRow->appendBoolean( rProp, rData.getIsFolder() );
1040 }
1041 else if ( rProp.Name.equalsAsciiL(
1042 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
1043 {
1044 xRow->appendObject(
1045 rProp, uno::makeAny( rData.getCreatableContentsInfo() ) );
1046 }
1047 else if ( rProp.Name.equalsAsciiL(
1048 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) )
1049 {
1050 // Storage is only supported by folders.
1051 ContentType eType = rData.getType();
1052 if ( eType == FOLDER )
1053 xRow->appendObject(
1054 rProp,
1055 uno::makeAny(
1056 pProvider->queryStorageClone( rContentId ) ) );
1057 else
1058 xRow->appendVoid( rProp );
1059 }
1060 else if ( rProp.Name.equalsAsciiL(
1061 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) )
1062 {
1063 // DocumentModel is only supported by documents.
1064 ContentType eType = rData.getType();
1065 if ( eType == DOCUMENT )
1066 xRow->appendObject(
1067 rProp,
1068 uno::makeAny(
1069 pProvider->queryDocumentModel( rContentId ) ) );
1070 else
1071 xRow->appendVoid( rProp );
1072 }
1073 else
1074 {
1075 // Not a Core Property! Maybe it's an Additional Core Property?!
1076
1077 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1078 {
1079 xAdditionalPropSet
1080 = uno::Reference< beans::XPropertySet >(
1081 pProvider->getAdditionalPropertySet( rContentId,
1082 sal_False ),
1083 uno::UNO_QUERY );
1084 bTriedToGetAdditonalPropSet = sal_True;
1085 }
1086
1087 if ( xAdditionalPropSet.is() )
1088 {
1089 if ( !xRow->appendPropertySetValue(
1090 xAdditionalPropSet,
1091 rProp ) )
1092 {
1093 // Append empty entry.
1094 xRow->appendVoid( rProp );
1095 }
1096 }
1097 else
1098 {
1099 // Append empty entry.
1100 xRow->appendVoid( rProp );
1101 }
1102 }
1103 }
1104 }
1105 else
1106 {
1107 // Append all Core Properties.
1108 xRow->appendString (
1109 beans::Property( rtl::OUString::createFromAscii( "ContentType" ),
1110 -1,
1111 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1112 beans::PropertyAttribute::BOUND
1113 | beans::PropertyAttribute::READONLY ),
1114 rData.getContentType() );
1115
1116 ContentType eType = rData.getType();
1117
1118 xRow->appendString (
1119 beans::Property( rtl::OUString::createFromAscii( "Title" ),
1120 -1,
1121 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1122 // Title is read-only for root and documents.
1123 beans::PropertyAttribute::BOUND ||
1124 ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
1125 ? beans::PropertyAttribute::READONLY
1126 : 0 ),
1127 rData.getTitle() );
1128 xRow->appendBoolean(
1129 beans::Property( rtl::OUString::createFromAscii( "IsDocument" ),
1130 -1,
1131 getCppuBooleanType(),
1132 beans::PropertyAttribute::BOUND
1133 | beans::PropertyAttribute::READONLY ),
1134 rData.getIsDocument() );
1135 xRow->appendBoolean(
1136 beans::Property( rtl::OUString::createFromAscii( "IsFolder" ),
1137 -1,
1138 getCppuBooleanType(),
1139 beans::PropertyAttribute::BOUND
1140 | beans::PropertyAttribute::READONLY ),
1141 rData.getIsFolder() );
1142 xRow->appendObject(
1143 beans::Property(
1144 rtl::OUString::createFromAscii( "CreatableContentsInfo" ),
1145 -1,
1146 getCppuType( static_cast<
1147 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
1148 beans::PropertyAttribute::BOUND
1149 | beans::PropertyAttribute::READONLY ),
1150 uno::makeAny( rData.getCreatableContentsInfo() ) );
1151
1152 // Storage is only supported by folders.
1153 if ( eType == FOLDER )
1154 xRow->appendObject(
1155 beans::Property( rtl::OUString::createFromAscii( "Storage" ),
1156 -1,
1157 getCppuType(
1158 static_cast<
1159 const uno::Reference< embed::XStorage > * >( 0 ) ),
1160 beans::PropertyAttribute::BOUND
1161 | beans::PropertyAttribute::READONLY ),
1162 uno::makeAny( pProvider->queryStorageClone( rContentId ) ) );
1163
1164 // DocumentModel is only supported by documents.
1165 if ( eType == DOCUMENT )
1166 xRow->appendObject(
1167 beans::Property( rtl::OUString::createFromAscii( "DocumentModel" ),
1168 -1,
1169 getCppuType(
1170 static_cast<
1171 const uno::Reference< frame::XModel > * >( 0 ) ),
1172 beans::PropertyAttribute::BOUND
1173 | beans::PropertyAttribute::READONLY ),
1174 uno::makeAny(
1175 pProvider->queryDocumentModel( rContentId ) ) );
1176
1177 // Append all Additional Core Properties.
1178
1179 uno::Reference< beans::XPropertySet > xSet(
1180 pProvider->getAdditionalPropertySet( rContentId, sal_False ),
1181 uno::UNO_QUERY );
1182 xRow->appendPropertySet( xSet );
1183 }
1184
1185 return uno::Reference< sdbc::XRow >( xRow.get() );
1186 }
1187
1188 //=========================================================================
getPropertyValues(const uno::Sequence<beans::Property> & rProperties)1189 uno::Reference< sdbc::XRow > Content::getPropertyValues(
1190 const uno::Sequence< beans::Property >& rProperties )
1191 {
1192 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1193 return getPropertyValues( m_xSMgr,
1194 rProperties,
1195 m_aProps,
1196 m_pProvider,
1197 m_xIdentifier->getContentIdentifier() );
1198 }
1199
1200 //=========================================================================
setPropertyValues(const uno::Sequence<beans::PropertyValue> & rValues,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1201 uno::Sequence< uno::Any > Content::setPropertyValues(
1202 const uno::Sequence< beans::PropertyValue >& rValues,
1203 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1204 throw( uno::Exception )
1205 {
1206 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1207
1208 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1209 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1210 sal_Int32 nChanged = 0;
1211
1212 beans::PropertyChangeEvent aEvent;
1213 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1214 aEvent.Further = sal_False;
1215 // aEvent.PropertyName =
1216 aEvent.PropertyHandle = -1;
1217 // aEvent.OldValue =
1218 // aEvent.NewValue =
1219
1220 const beans::PropertyValue* pValues = rValues.getConstArray();
1221 sal_Int32 nCount = rValues.getLength();
1222
1223 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1224 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1225
1226 sal_Bool bExchange = sal_False;
1227 rtl::OUString aOldTitle;
1228 sal_Int32 nTitlePos = -1;
1229
1230 for ( sal_Int32 n = 0; n < nCount; ++n )
1231 {
1232 const beans::PropertyValue& rValue = pValues[ n ];
1233
1234 if ( rValue.Name.equalsAsciiL(
1235 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1236 {
1237 // Read-only property!
1238 aRet[ n ] <<= lang::IllegalAccessException(
1239 rtl::OUString::createFromAscii(
1240 "Property is read-only!" ),
1241 static_cast< cppu::OWeakObject * >( this ) );
1242 }
1243 else if ( rValue.Name.equalsAsciiL(
1244 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1245 {
1246 // Read-only property!
1247 aRet[ n ] <<= lang::IllegalAccessException(
1248 rtl::OUString::createFromAscii(
1249 "Property is read-only!" ),
1250 static_cast< cppu::OWeakObject * >( this ) );
1251 }
1252 else if ( rValue.Name.equalsAsciiL(
1253 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1254 {
1255 // Read-only property!
1256 aRet[ n ] <<= lang::IllegalAccessException(
1257 rtl::OUString::createFromAscii(
1258 "Property is read-only!" ),
1259 static_cast< cppu::OWeakObject * >( this ) );
1260 }
1261 else if ( rValue.Name.equalsAsciiL(
1262 RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
1263 {
1264 // Read-only property!
1265 aRet[ n ] <<= lang::IllegalAccessException(
1266 rtl::OUString::createFromAscii(
1267 "Property is read-only!" ),
1268 static_cast< cppu::OWeakObject * >( this ) );
1269 }
1270 else if ( rValue.Name.equalsAsciiL(
1271 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1272 {
1273 // Title is read-only for root and documents.
1274 ContentType eType = m_aProps.getType();
1275 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
1276 {
1277 aRet[ n ] <<= lang::IllegalAccessException(
1278 rtl::OUString::createFromAscii(
1279 "Property is read-only!" ),
1280 static_cast< cppu::OWeakObject * >( this ) );
1281 }
1282 else
1283 {
1284 rtl::OUString aNewValue;
1285 if ( rValue.Value >>= aNewValue )
1286 {
1287 // No empty titles!
1288 if ( aNewValue.getLength() > 0 )
1289 {
1290 if ( aNewValue != m_aProps.getTitle() )
1291 {
1292 // modified title -> modified URL -> exchange !
1293 if ( m_eState == PERSISTENT )
1294 bExchange = sal_True;
1295
1296 aOldTitle = m_aProps.getTitle();
1297 m_aProps.setTitle( aNewValue );
1298
1299 // property change event will be sent later...
1300
1301 // remember position within sequence of values
1302 // (for error handling).
1303 nTitlePos = n;
1304 }
1305 }
1306 else
1307 {
1308 aRet[ n ] <<= lang::IllegalArgumentException(
1309 rtl::OUString::createFromAscii(
1310 "Empty Title not allowed!" ),
1311 static_cast< cppu::OWeakObject * >( this ),
1312 -1 );
1313 }
1314 }
1315 else
1316 {
1317 aRet[ n ] <<= beans::IllegalTypeException(
1318 rtl::OUString::createFromAscii(
1319 "Title Property value has wrong type!" ),
1320 static_cast< cppu::OWeakObject * >( this ) );
1321 }
1322 }
1323 }
1324 else if ( rValue.Name.equalsAsciiL(
1325 RTL_CONSTASCII_STRINGPARAM( "Storage" ) ) )
1326 {
1327 ContentType eType = m_aProps.getType();
1328 if ( eType == FOLDER )
1329 {
1330 aRet[ n ] <<= lang::IllegalAccessException(
1331 rtl::OUString::createFromAscii(
1332 "Property is read-only!" ),
1333 static_cast< cppu::OWeakObject * >( this ) );
1334 }
1335 else
1336 {
1337 // Storage is only supported by folders.
1338 aRet[ n ] <<= beans::UnknownPropertyException(
1339 rtl::OUString::createFromAscii(
1340 "Storage property only supported by folders" ),
1341 static_cast< cppu::OWeakObject * >( this ) );
1342 }
1343 }
1344 else if ( rValue.Name.equalsAsciiL(
1345 RTL_CONSTASCII_STRINGPARAM( "DocumentModel" ) ) )
1346 {
1347 ContentType eType = m_aProps.getType();
1348 if ( eType == DOCUMENT )
1349 {
1350 aRet[ n ] <<= lang::IllegalAccessException(
1351 rtl::OUString::createFromAscii(
1352 "Property is read-only!" ),
1353 static_cast< cppu::OWeakObject * >( this ) );
1354 }
1355 else
1356 {
1357 // Storage is only supported by folders.
1358 aRet[ n ] <<= beans::UnknownPropertyException(
1359 rtl::OUString::createFromAscii(
1360 "DocumentModel property only supported by "
1361 "documents" ),
1362 static_cast< cppu::OWeakObject * >( this ) );
1363 }
1364 }
1365 else
1366 {
1367 // Not a Core Property! Maybe it's an Additional Core Property?!
1368
1369 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1370 {
1371 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1372 bTriedToGetAdditonalPropSet = sal_True;
1373 }
1374
1375 if ( xAdditionalPropSet.is() )
1376 {
1377 try
1378 {
1379 uno::Any aOldValue = xAdditionalPropSet->getPropertyValue(
1380 rValue.Name );
1381 if ( aOldValue != rValue.Value )
1382 {
1383 xAdditionalPropSet->setPropertyValue(
1384 rValue.Name, rValue.Value );
1385
1386 aEvent.PropertyName = rValue.Name;
1387 aEvent.OldValue = aOldValue;
1388 aEvent.NewValue = rValue.Value;
1389
1390 aChanges.getArray()[ nChanged ] = aEvent;
1391 nChanged++;
1392 }
1393 }
1394 catch ( beans::UnknownPropertyException const & e )
1395 {
1396 aRet[ n ] <<= e;
1397 }
1398 catch ( lang::WrappedTargetException const & e )
1399 {
1400 aRet[ n ] <<= e;
1401 }
1402 catch ( beans::PropertyVetoException const & e )
1403 {
1404 aRet[ n ] <<= e;
1405 }
1406 catch ( lang::IllegalArgumentException const & e )
1407 {
1408 aRet[ n ] <<= e;
1409 }
1410 }
1411 else
1412 {
1413 aRet[ n ] <<= uno::Exception(
1414 rtl::OUString::createFromAscii(
1415 "No property set for storing the value!" ),
1416 static_cast< cppu::OWeakObject * >( this ) );
1417 }
1418 }
1419 }
1420
1421 if ( bExchange )
1422 {
1423 uno::Reference< ucb::XContentIdentifier > xOldId
1424 = m_xIdentifier;
1425 uno::Reference< ucb::XContentIdentifier > xNewId
1426 = makeNewIdentifier( m_aProps.getTitle() );
1427
1428 aGuard.clear();
1429 if ( exchangeIdentity( xNewId ) )
1430 {
1431 // Adapt persistent data.
1432 renameData( xOldId, xNewId );
1433
1434 // Adapt Additional Core Properties.
1435 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1436 xNewId->getContentIdentifier(),
1437 sal_True );
1438 }
1439 else
1440 {
1441 // Roll-back.
1442 m_aProps.setTitle( aOldTitle );
1443 aOldTitle = rtl::OUString();
1444
1445 // Set error .
1446 aRet[ nTitlePos ] <<= uno::Exception(
1447 rtl::OUString::createFromAscii( "Exchange failed!" ),
1448 static_cast< cppu::OWeakObject * >( this ) );
1449 }
1450 }
1451
1452 if ( aOldTitle.getLength() )
1453 {
1454 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
1455 aEvent.OldValue = uno::makeAny( aOldTitle );
1456 aEvent.NewValue = uno::makeAny( m_aProps.getTitle() );
1457
1458 aChanges.getArray()[ nChanged ] = aEvent;
1459 nChanged++;
1460 }
1461
1462 if ( nChanged > 0 )
1463 {
1464 // Save changes, if content was already made persistent.
1465 if ( !bExchange && ( m_eState == PERSISTENT ) )
1466 {
1467 if ( !storeData( uno::Reference< io::XInputStream >(), xEnv ) )
1468 {
1469 uno::Any aProps
1470 = uno::makeAny(
1471 beans::PropertyValue(
1472 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1473 "Uri")),
1474 -1,
1475 uno::makeAny(m_xIdentifier->
1476 getContentIdentifier()),
1477 beans::PropertyState_DIRECT_VALUE));
1478 ucbhelper::cancelCommandExecution(
1479 ucb::IOErrorCode_CANT_WRITE,
1480 uno::Sequence< uno::Any >(&aProps, 1),
1481 xEnv,
1482 rtl::OUString::createFromAscii(
1483 "Cannot store persistent data!" ),
1484 this );
1485 // Unreachable
1486 }
1487 }
1488
1489 aChanges.realloc( nChanged );
1490
1491 aGuard.clear();
1492 notifyPropertiesChange( aChanges );
1493 }
1494
1495 return aRet;
1496 }
1497
1498 //=========================================================================
open(const ucb::OpenCommandArgument2 & rArg,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1499 uno::Any Content::open(
1500 const ucb::OpenCommandArgument2& rArg,
1501 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1502 throw( uno::Exception )
1503 {
1504 if ( rArg.Mode == ucb::OpenMode::ALL ||
1505 rArg.Mode == ucb::OpenMode::FOLDERS ||
1506 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1507 {
1508 //////////////////////////////////////////////////////////////////
1509 // open command for a folder content
1510 //////////////////////////////////////////////////////////////////
1511
1512 uno::Reference< ucb::XDynamicResultSet > xSet
1513 = new DynamicResultSet( m_xSMgr, this, rArg );
1514 return uno::makeAny( xSet );
1515 }
1516 else
1517 {
1518 //////////////////////////////////////////////////////////////////
1519 // open command for a document content
1520 //////////////////////////////////////////////////////////////////
1521
1522 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1523 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1524 {
1525 // Currently(?) unsupported.
1526 ucbhelper::cancelCommandExecution(
1527 uno::makeAny( ucb::UnsupportedOpenModeException(
1528 rtl::OUString(),
1529 static_cast< cppu::OWeakObject * >( this ),
1530 sal_Int16( rArg.Mode ) ) ),
1531 xEnv );
1532 // Unreachable
1533 }
1534
1535 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1536
1537 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
1538
1539 uno::Reference< io::XActiveDataStreamer > xDataStreamer(
1540 rArg.Sink, uno::UNO_QUERY );
1541 if ( xDataStreamer.is() )
1542 {
1543 // May throw CommandFailedException, DocumentPasswordRequest!
1544 uno::Reference< io::XStream > xStream = getStream( xEnv );
1545 if ( !xStream.is() )
1546 {
1547 // No interaction if we are not persistent!
1548 uno::Any aProps
1549 = uno::makeAny(
1550 beans::PropertyValue(
1551 rtl::OUString(
1552 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1553 -1,
1554 uno::makeAny(m_xIdentifier->
1555 getContentIdentifier()),
1556 beans::PropertyState_DIRECT_VALUE));
1557 ucbhelper::cancelCommandExecution(
1558 ucb::IOErrorCode_CANT_READ,
1559 uno::Sequence< uno::Any >(&aProps, 1),
1560 m_eState == PERSISTENT
1561 ? xEnv
1562 : uno::Reference< ucb::XCommandEnvironment >(),
1563 rtl::OUString::createFromAscii(
1564 "Got no data stream!" ),
1565 this );
1566 // Unreachable
1567 }
1568
1569 // Done.
1570 xDataStreamer->setStream( xStream );
1571 }
1572 else
1573 {
1574 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1575 if ( xOut.is() )
1576 {
1577 // PUSH: write data into xOut
1578
1579 // May throw CommandFailedException, DocumentPasswordRequest!
1580 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1581 if ( !xIn.is() )
1582 {
1583 // No interaction if we are not persistent!
1584 uno::Any aProps
1585 = uno::makeAny(
1586 beans::PropertyValue(
1587 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1588 "Uri")),
1589 -1,
1590 uno::makeAny(m_xIdentifier->
1591 getContentIdentifier()),
1592 beans::PropertyState_DIRECT_VALUE));
1593 ucbhelper::cancelCommandExecution(
1594 ucb::IOErrorCode_CANT_READ,
1595 uno::Sequence< uno::Any >(&aProps, 1),
1596 m_eState == PERSISTENT
1597 ? xEnv
1598 : uno::Reference< ucb::XCommandEnvironment >(),
1599 rtl::OUString::createFromAscii( "Got no data stream!" ),
1600 this );
1601 // Unreachable
1602 }
1603
1604 try
1605 {
1606 uno::Sequence< sal_Int8 > aBuffer;
1607 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1608
1609 while ( nRead > 0 )
1610 {
1611 aBuffer.realloc( nRead );
1612 xOut->writeBytes( aBuffer );
1613 aBuffer.realloc( 0 );
1614 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1615 }
1616
1617 xOut->closeOutput();
1618 }
1619 catch ( io::NotConnectedException const & )
1620 {
1621 // closeOutput, readSomeBytes, writeBytes
1622 }
1623 catch ( io::BufferSizeExceededException const & )
1624 {
1625 // closeOutput, readSomeBytes, writeBytes
1626 }
1627 catch ( io::IOException const & )
1628 {
1629 // closeOutput, readSomeBytes, writeBytes
1630 }
1631 }
1632 else
1633 {
1634 uno::Reference< io::XActiveDataSink > xDataSink(
1635 rArg.Sink, uno::UNO_QUERY );
1636 if ( xDataSink.is() )
1637 {
1638 // PULL: wait for client read
1639
1640 // May throw CommandFailedException, DocumentPasswordRequest!
1641 uno::Reference< io::XInputStream > xIn = getInputStream( xEnv );
1642 if ( !xIn.is() )
1643 {
1644 // No interaction if we are not persistent!
1645 uno::Any aProps
1646 = uno::makeAny(
1647 beans::PropertyValue(
1648 rtl::OUString(
1649 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1650 -1,
1651 uno::makeAny(m_xIdentifier->
1652 getContentIdentifier()),
1653 beans::PropertyState_DIRECT_VALUE));
1654 ucbhelper::cancelCommandExecution(
1655 ucb::IOErrorCode_CANT_READ,
1656 uno::Sequence< uno::Any >(&aProps, 1),
1657 m_eState == PERSISTENT
1658 ? xEnv
1659 : uno::Reference<
1660 ucb::XCommandEnvironment >(),
1661 rtl::OUString::createFromAscii(
1662 "Got no data stream!" ),
1663 this );
1664 // Unreachable
1665 }
1666
1667 // Done.
1668 xDataSink->setInputStream( xIn );
1669 }
1670 else
1671 {
1672 ucbhelper::cancelCommandExecution(
1673 uno::makeAny(
1674 ucb::UnsupportedDataSinkException(
1675 rtl::OUString(),
1676 static_cast< cppu::OWeakObject * >( this ),
1677 rArg.Sink ) ),
1678 xEnv );
1679 // Unreachable
1680 }
1681 }
1682 }
1683 }
1684
1685 return uno::Any();
1686 }
1687
1688 //=========================================================================
insert(const uno::Reference<io::XInputStream> & xData,sal_Int32 nNameClashResolve,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1689 void Content::insert( const uno::Reference< io::XInputStream >& xData,
1690 sal_Int32 nNameClashResolve,
1691 const uno::Reference<
1692 ucb::XCommandEnvironment > & xEnv )
1693 throw( uno::Exception )
1694 {
1695 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1696
1697 ContentType eType = m_aProps.getType();
1698
1699 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1700 "insert command only supported by streams and folders!" );
1701
1702 Uri aUri( m_xIdentifier->getContentIdentifier() );
1703
1704 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
1705 #if OSL_DEBUG_LEVEL > 0
1706 if ( eType == STREAM )
1707 {
1708 Uri aParentUri( aUri.getParentUri() );
1709 OSL_ENSURE( !aParentUri.isDocument(),
1710 "insert command not supported by streams that are direct "
1711 "children of document root!" );
1712 }
1713 #endif
1714 #endif
1715
1716 // Check, if all required properties were set.
1717 if ( eType == FOLDER )
1718 {
1719 // Required: Title
1720
1721 if ( m_aProps.getTitle().getLength() == 0 )
1722 m_aProps.setTitle( aUri.getDecodedName() );
1723 }
1724 else // stream
1725 {
1726 // Required: data
1727
1728 if ( !xData.is() )
1729 {
1730 ucbhelper::cancelCommandExecution(
1731 uno::makeAny( ucb::MissingInputStreamException(
1732 rtl::OUString(),
1733 static_cast< cppu::OWeakObject * >( this ) ) ),
1734 xEnv );
1735 // Unreachable
1736 }
1737
1738 // Required: Title
1739
1740 if ( m_aProps.getTitle().getLength() == 0 )
1741 m_aProps.setTitle( aUri.getDecodedName() );
1742 }
1743
1744 rtl::OUStringBuffer aNewURL = aUri.getParentUri();
1745 aNewURL.append( m_aProps.getTitle() );
1746 Uri aNewUri( aNewURL.makeStringAndClear() );
1747
1748 // Handle possible name clash...
1749 switch ( nNameClashResolve )
1750 {
1751 // fail.
1752 case ucb::NameClash::ERROR:
1753 if ( hasData( aNewUri ) )
1754 {
1755 ucbhelper::cancelCommandExecution(
1756 uno::makeAny( ucb::NameClashException(
1757 rtl::OUString(),
1758 static_cast< cppu::OWeakObject * >( this ),
1759 task::InteractionClassification_ERROR,
1760 m_aProps.getTitle() ) ),
1761 xEnv );
1762 // Unreachable
1763 }
1764 break;
1765
1766 // replace (possibly) existing object.
1767 case ucb::NameClash::OVERWRITE:
1768 break;
1769
1770 // "invent" a new valid title.
1771 case ucb::NameClash::RENAME:
1772 if ( hasData( aNewUri ) )
1773 {
1774 sal_Int32 nTry = 0;
1775
1776 do
1777 {
1778 rtl::OUStringBuffer aNew = aNewUri.getUri();
1779 aNew.appendAscii( "_" );
1780 aNew.append( rtl::OUString::valueOf( ++nTry ) );
1781 aNewUri.setUri( aNew.makeStringAndClear() );
1782 }
1783 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1784
1785 if ( nTry == 1000 )
1786 {
1787 ucbhelper::cancelCommandExecution(
1788 uno::makeAny(
1789 ucb::UnsupportedNameClashException(
1790 rtl::OUString::createFromAscii(
1791 "Unable to resolve name clash!" ),
1792 static_cast< cppu::OWeakObject * >( this ),
1793 nNameClashResolve ) ),
1794 xEnv );
1795 // Unreachable
1796 }
1797 else
1798 {
1799 rtl::OUStringBuffer aNewTitle = m_aProps.getTitle();
1800 aNewTitle.appendAscii( "_" );
1801 aNewTitle.append( rtl::OUString::valueOf( ++nTry ) );
1802 m_aProps.setTitle( aNewTitle.makeStringAndClear() );
1803 }
1804 }
1805 break;
1806
1807 case ucb::NameClash::KEEP: // deprecated
1808 case ucb::NameClash::ASK:
1809 default:
1810 if ( hasData( aNewUri ) )
1811 {
1812 ucbhelper::cancelCommandExecution(
1813 uno::makeAny(
1814 ucb::UnsupportedNameClashException(
1815 rtl::OUString(),
1816 static_cast< cppu::OWeakObject * >( this ),
1817 nNameClashResolve ) ),
1818 xEnv );
1819 // Unreachable
1820 }
1821 break;
1822 }
1823
1824 // Identifier changed?
1825 sal_Bool bNewId = ( aUri != aNewUri );
1826
1827 if ( bNewId )
1828 {
1829 m_xIdentifier
1830 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewUri.getUri() );
1831 }
1832
1833 if ( !storeData( xData, xEnv ) )
1834 {
1835 uno::Any aProps
1836 = uno::makeAny(beans::PropertyValue(
1837 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1838 "Uri")),
1839 -1,
1840 uno::makeAny(m_xIdentifier->
1841 getContentIdentifier()),
1842 beans::PropertyState_DIRECT_VALUE));
1843 ucbhelper::cancelCommandExecution(
1844 ucb::IOErrorCode_CANT_WRITE,
1845 uno::Sequence< uno::Any >(&aProps, 1),
1846 xEnv,
1847 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1848 this );
1849 // Unreachable
1850 }
1851
1852 m_eState = PERSISTENT;
1853
1854 if ( bNewId )
1855 {
1856 //loadData( m_pProvider, m_aUri, m_aProps );
1857
1858 aGuard.clear();
1859 inserted();
1860 }
1861 }
1862
1863 //=========================================================================
destroy(sal_Bool bDeletePhysical,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1864 void Content::destroy( sal_Bool bDeletePhysical,
1865 const uno::Reference<
1866 ucb::XCommandEnvironment > & xEnv )
1867 throw( uno::Exception )
1868 {
1869 // @@@ take care about bDeletePhysical -> trashcan support
1870
1871 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1872
1873 ContentType eType = m_aProps.getType();
1874
1875 OSL_ENSURE( ( eType == FOLDER ) || ( eType == STREAM ),
1876 "delete command only supported by streams and folders!" );
1877
1878 uno::Reference< ucb::XContent > xThis = this;
1879
1880 // Persistent?
1881 if ( m_eState != PERSISTENT )
1882 {
1883 ucbhelper::cancelCommandExecution(
1884 uno::makeAny( ucb::UnsupportedCommandException(
1885 rtl::OUString::createFromAscii(
1886 "Not persistent!" ),
1887 static_cast< cppu::OWeakObject * >( this ) ) ),
1888 xEnv );
1889 // Unreachable
1890 }
1891
1892 m_eState = DEAD;
1893
1894 aGuard.clear();
1895 deleted();
1896
1897 if ( eType == FOLDER )
1898 {
1899 // Process instanciated children...
1900
1901 ContentRefList aChildren;
1902 queryChildren( aChildren );
1903
1904 ContentRefList::const_iterator it = aChildren.begin();
1905 ContentRefList::const_iterator end = aChildren.end();
1906
1907 while ( it != end )
1908 {
1909 (*it)->destroy( bDeletePhysical, xEnv );
1910 ++it;
1911 }
1912 }
1913 }
1914
1915 //=========================================================================
notifyDocumentClosed()1916 void Content::notifyDocumentClosed()
1917 {
1918 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1919
1920 m_eState = DEAD;
1921
1922 // @@@ anything else to reset or such?
1923
1924 // callback follows!
1925 aGuard.clear();
1926
1927 // Propagate destruction to content event listeners
1928 // Remove this from provider's content list.
1929 deleted();
1930 }
1931
1932 //=========================================================================
1933 uno::Reference< ucb::XContent >
queryChildContent(const rtl::OUString & rRelativeChildUri)1934 Content::queryChildContent( const rtl::OUString & rRelativeChildUri )
1935 {
1936 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1937
1938 const rtl::OUString aMyId = getIdentifier()->getContentIdentifier();
1939 rtl::OUStringBuffer aBuf( aMyId );
1940 if ( aMyId.getStr()[ aMyId.getLength() - 1 ] != sal_Unicode( '/' ) )
1941 aBuf.appendAscii( "/" );
1942 if ( rRelativeChildUri.getStr()[ 0 ] != sal_Unicode( '/' ) )
1943 aBuf.append( rRelativeChildUri );
1944 else
1945 aBuf.append( rRelativeChildUri.copy( 1 ) );
1946
1947 uno::Reference< ucb::XContentIdentifier > xChildId
1948 = new ::ucbhelper::ContentIdentifier(
1949 m_xSMgr, aBuf.makeStringAndClear() );
1950
1951 uno::Reference< ucb::XContent > xChild;
1952 try
1953 {
1954 xChild = m_pProvider->queryContent( xChildId );
1955 }
1956 catch ( ucb::IllegalIdentifierException const & )
1957 {
1958 // handled below.
1959 }
1960
1961 OSL_ENSURE( xChild.is(),
1962 "Content::queryChildContent - unable to create child content!" );
1963 return xChild;
1964 }
1965
1966 //=========================================================================
notifyChildRemoved(const rtl::OUString & rRelativeChildUri)1967 void Content::notifyChildRemoved( const rtl::OUString & rRelativeChildUri )
1968 {
1969 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1970
1971 // Ugly! Need to create child content object, just to fill event properly.
1972 uno::Reference< ucb::XContent > xChild
1973 = queryChildContent( rRelativeChildUri );
1974
1975 if ( xChild.is() )
1976 {
1977 // callback follows!
1978 aGuard.clear();
1979
1980 // Notify "REMOVED" event.
1981 ucb::ContentEvent aEvt(
1982 static_cast< cppu::OWeakObject * >( this ),
1983 ucb::ContentAction::REMOVED,
1984 xChild,
1985 getIdentifier() );
1986 notifyContentEvent( aEvt );
1987 }
1988 }
1989
1990 //=========================================================================
notifyChildInserted(const rtl::OUString & rRelativeChildUri)1991 void Content::notifyChildInserted( const rtl::OUString & rRelativeChildUri )
1992 {
1993 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1994
1995 // Ugly! Need to create child content object, just to fill event properly.
1996 uno::Reference< ucb::XContent > xChild
1997 = queryChildContent( rRelativeChildUri );
1998
1999 if ( xChild.is() )
2000 {
2001 // callback follows!
2002 aGuard.clear();
2003
2004 // Notify "INSERTED" event.
2005 ucb::ContentEvent aEvt(
2006 static_cast< cppu::OWeakObject * >( this ),
2007 ucb::ContentAction::INSERTED,
2008 xChild,
2009 getIdentifier() );
2010 notifyContentEvent( aEvt );
2011 }
2012 }
2013
2014 //=========================================================================
transfer(const ucb::TransferInfo & rInfo,const uno::Reference<ucb::XCommandEnvironment> & xEnv)2015 void Content::transfer(
2016 const ucb::TransferInfo& rInfo,
2017 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2018 throw( uno::Exception )
2019 {
2020 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
2021
2022 // Persistent?
2023 if ( m_eState != PERSISTENT )
2024 {
2025 ucbhelper::cancelCommandExecution(
2026 uno::makeAny( ucb::UnsupportedCommandException(
2027 rtl::OUString::createFromAscii(
2028 "Not persistent!" ),
2029 static_cast< cppu::OWeakObject * >( this ) ) ),
2030 xEnv );
2031 // Unreachable
2032 }
2033
2034 // Does source URI scheme match? Only vnd.sun.star.tdoc is supported.
2035
2036 if ( ( rInfo.SourceURL.getLength() < TDOC_URL_SCHEME_LENGTH + 2 ) )
2037 {
2038 // Invalid length (to short).
2039 ucbhelper::cancelCommandExecution(
2040 uno::makeAny( ucb::InteractiveBadTransferURLException(
2041 rtl::OUString(),
2042 static_cast< cppu::OWeakObject * >( this ) ) ),
2043 xEnv );
2044 // Unreachable
2045 }
2046
2047 rtl::OUString aScheme
2048 = rInfo.SourceURL.copy( 0, TDOC_URL_SCHEME_LENGTH + 2 )
2049 .toAsciiLowerCase();
2050 if ( !aScheme.equalsAsciiL(
2051 RTL_CONSTASCII_STRINGPARAM( TDOC_URL_SCHEME ":/" ) ) )
2052 {
2053 // Invalid scheme.
2054 ucbhelper::cancelCommandExecution(
2055 uno::makeAny( ucb::InteractiveBadTransferURLException(
2056 rtl::OUString(),
2057 static_cast< cppu::OWeakObject * >( this ) ) ),
2058 xEnv );
2059 // Unreachable
2060 }
2061
2062 // Does source URI describe a tdoc folder or stream?
2063 Uri aSourceUri( rInfo.SourceURL );
2064 if ( !aSourceUri.isValid() )
2065 {
2066 ucbhelper::cancelCommandExecution(
2067 uno::makeAny( lang::IllegalArgumentException(
2068 rtl::OUString::createFromAscii(
2069 "Invalid source URI! Syntax!" ),
2070 static_cast< cppu::OWeakObject * >( this ),
2071 -1 ) ),
2072 xEnv );
2073 // Unreachable
2074 }
2075
2076 if ( aSourceUri.isRoot() || aSourceUri.isDocument() )
2077 {
2078 ucbhelper::cancelCommandExecution(
2079 uno::makeAny( lang::IllegalArgumentException(
2080 rtl::OUString::createFromAscii(
2081 "Invalid source URI! "
2082 "Must describe a folder or stream!" ),
2083 static_cast< cppu::OWeakObject * >( this ),
2084 -1 ) ),
2085 xEnv );
2086 // Unreachable
2087 }
2088
2089 // Is source not a parent of me / not me?
2090 rtl::OUString aId = m_xIdentifier->getContentIdentifier();
2091 sal_Int32 nPos = aId.lastIndexOf( '/' );
2092 if ( nPos != ( aId.getLength() - 1 ) )
2093 {
2094 // No trailing slash found. Append.
2095 aId += rtl::OUString::createFromAscii( "/" );
2096 }
2097
2098 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
2099 {
2100 if ( aId.compareTo(
2101 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
2102 {
2103 uno::Any aProps
2104 = uno::makeAny(beans::PropertyValue(
2105 rtl::OUString(
2106 RTL_CONSTASCII_USTRINGPARAM("Uri")),
2107 -1,
2108 uno::makeAny( rInfo.SourceURL ),
2109 beans::PropertyState_DIRECT_VALUE));
2110 ucbhelper::cancelCommandExecution(
2111 ucb::IOErrorCode_RECURSIVE,
2112 uno::Sequence< uno::Any >(&aProps, 1),
2113 xEnv,
2114 rtl::OUString::createFromAscii(
2115 "Target is equal to or is a child of source!" ),
2116 this );
2117 // Unreachable
2118 }
2119 }
2120
2121 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
2122 if ( m_aProps.getType() == DOCUMENT )
2123 {
2124 bool bOK = false;
2125
2126 uno::Reference< embed::XStorage > xStorage
2127 = m_pProvider->queryStorage(
2128 aSourceUri.getParentUri(), READ_WRITE_NOCREATE );
2129 if ( xStorage.is() )
2130 {
2131 try
2132 {
2133 if ( xStorage->isStreamElement( aSourceUri.getDecodedName() ) )
2134 {
2135 ucbhelper::cancelCommandExecution(
2136 uno::makeAny( lang::IllegalArgumentException(
2137 rtl::OUString::createFromAscii(
2138 "Invalid source URI! "
2139 "Streams cannot be created as "
2140 "children of document root!" ),
2141 static_cast< cppu::OWeakObject * >(
2142 this ),
2143 -1 ) ),
2144 xEnv );
2145 // Unreachable
2146 }
2147 bOK = true;
2148 }
2149 catch ( container::NoSuchElementException const & )
2150 {
2151 // handled below.
2152 }
2153 catch ( lang::IllegalArgumentException const & )
2154 {
2155 // handled below.
2156 }
2157 catch ( embed::InvalidStorageException const & )
2158 {
2159 // handled below.
2160 }
2161 }
2162
2163 if ( !bOK )
2164 {
2165 ucbhelper::cancelCommandExecution(
2166 uno::makeAny( lang::IllegalArgumentException(
2167 rtl::OUString::createFromAscii(
2168 "Invalid source URI! "
2169 "Unabale to determine source type!" ),
2170 static_cast< cppu::OWeakObject * >( this ),
2171 -1 ) ),
2172 xEnv );
2173 // Unreachable
2174 }
2175 }
2176 #endif
2177
2178 /////////////////////////////////////////////////////////////////////////
2179 // Copy data.
2180 /////////////////////////////////////////////////////////////////////////
2181
2182 rtl::OUString aNewName( rInfo.NewTitle.getLength() > 0
2183 ? rInfo.NewTitle
2184 : aSourceUri.getDecodedName() );
2185
2186 if ( !copyData( aSourceUri, aNewName ) )
2187 {
2188 uno::Any aProps
2189 = uno::makeAny(
2190 beans::PropertyValue(
2191 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2192 "Uri")),
2193 -1,
2194 uno::makeAny( rInfo.SourceURL ),
2195 beans::PropertyState_DIRECT_VALUE));
2196 ucbhelper::cancelCommandExecution(
2197 ucb::IOErrorCode_CANT_WRITE,
2198 uno::Sequence< uno::Any >(&aProps, 1),
2199 xEnv,
2200 rtl::OUString(
2201 RTL_CONSTASCII_USTRINGPARAM( "Cannot copy data!" ) ),
2202 this );
2203 // Unreachable
2204 }
2205
2206 /////////////////////////////////////////////////////////////////////////
2207 // Copy own and all children's Additional Core Properties.
2208 /////////////////////////////////////////////////////////////////////////
2209
2210 rtl::OUString aTargetUri = m_xIdentifier->getContentIdentifier();
2211 if ( ( aTargetUri.lastIndexOf( '/' ) + 1 ) != aTargetUri.getLength() )
2212 aTargetUri += rtl::OUString::createFromAscii( "/" );
2213
2214 if ( rInfo.NewTitle.getLength() > 0 )
2215 aTargetUri += ::ucb_impl::urihelper::encodeSegment( rInfo.NewTitle );
2216 else
2217 aTargetUri += aSourceUri.getName();
2218
2219 if ( !copyAdditionalPropertySet(
2220 aSourceUri.getUri(), aTargetUri, sal_True ) )
2221 {
2222 uno::Any aProps
2223 = uno::makeAny(
2224 beans::PropertyValue(
2225 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2226 "Uri")),
2227 -1,
2228 uno::makeAny( rInfo.SourceURL ),
2229 beans::PropertyState_DIRECT_VALUE));
2230 ucbhelper::cancelCommandExecution(
2231 ucb::IOErrorCode_CANT_WRITE,
2232 uno::Sequence< uno::Any >(&aProps, 1),
2233 xEnv,
2234 rtl::OUString(
2235 RTL_CONSTASCII_USTRINGPARAM(
2236 "Cannot copy additional properties!" ) ),
2237 this );
2238 // Unreachable
2239 }
2240
2241 /////////////////////////////////////////////////////////////////////////
2242 // Propagate new content.
2243 /////////////////////////////////////////////////////////////////////////
2244
2245 rtl::Reference< Content > xTarget;
2246 try
2247 {
2248 uno::Reference< ucb::XContentIdentifier > xTargetId
2249 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aTargetUri );
2250
2251 // Note: The static cast is okay here, because its sure that
2252 // m_xProvider is always the WebDAVContentProvider.
2253 xTarget = static_cast< Content * >(
2254 m_pProvider->queryContent( xTargetId ).get() );
2255
2256 }
2257 catch ( ucb::IllegalIdentifierException const & )
2258 {
2259 // queryContent
2260 }
2261
2262 if ( !xTarget.is() )
2263 {
2264 uno::Any aProps
2265 = uno::makeAny(beans::PropertyValue(
2266 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2267 "Uri")),
2268 -1,
2269 uno::makeAny( aTargetUri ),
2270 beans::PropertyState_DIRECT_VALUE));
2271 ucbhelper::cancelCommandExecution(
2272 ucb::IOErrorCode_CANT_READ,
2273 uno::Sequence< uno::Any >(&aProps, 1),
2274 xEnv,
2275 rtl::OUString::createFromAscii(
2276 "Cannot instanciate target object!" ),
2277 this );
2278 // Unreachable
2279 }
2280
2281 // Announce transferred content in its new folder.
2282 xTarget->inserted();
2283
2284 /////////////////////////////////////////////////////////////////////////
2285 // Remove source, if requested
2286 /////////////////////////////////////////////////////////////////////////
2287
2288 if ( rInfo.MoveData )
2289 {
2290 rtl::Reference< Content > xSource;
2291 try
2292 {
2293 uno::Reference< ucb::XContentIdentifier >
2294 xSourceId = new ::ucbhelper::ContentIdentifier(
2295 m_xSMgr, rInfo.SourceURL );
2296
2297 // Note: The static cast is okay here, because its sure
2298 // that m_xProvider is always the ContentProvider.
2299 xSource = static_cast< Content * >(
2300 m_xProvider->queryContent( xSourceId ).get() );
2301 }
2302 catch ( ucb::IllegalIdentifierException const & )
2303 {
2304 // queryContent
2305 }
2306
2307 if ( !xSource.is() )
2308 {
2309 uno::Any aProps
2310 = uno::makeAny(beans::PropertyValue(
2311 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2312 "Uri")),
2313 -1,
2314 uno::makeAny( rInfo.SourceURL ),
2315 beans::PropertyState_DIRECT_VALUE));
2316 ucbhelper::cancelCommandExecution(
2317 ucb::IOErrorCode_CANT_READ,
2318 uno::Sequence< uno::Any >(&aProps, 1),
2319 xEnv,
2320 rtl::OUString::createFromAscii(
2321 "Cannot instanciate target object!" ),
2322 this );
2323 // Unreachable
2324 }
2325
2326 // Propagate destruction (recursively).
2327 xSource->destroy( sal_True, xEnv );
2328
2329 // Remove all persistent data of source and its children.
2330 if ( !xSource->removeData() )
2331 {
2332 uno::Any aProps
2333 = uno::makeAny(
2334 beans::PropertyValue(
2335 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2336 "Uri")),
2337 -1,
2338 uno::makeAny( rInfo.SourceURL ),
2339 beans::PropertyState_DIRECT_VALUE));
2340 ucbhelper::cancelCommandExecution(
2341 ucb::IOErrorCode_CANT_WRITE,
2342 uno::Sequence< uno::Any >(&aProps, 1),
2343 xEnv,
2344 rtl::OUString::createFromAscii(
2345 "Cannot remove persistent data of source object!" ),
2346 this );
2347 // Unreachable
2348 }
2349
2350 // Remove own and all children's Additional Core Properties.
2351 if ( !xSource->removeAdditionalPropertySet( sal_True ) )
2352 {
2353 uno::Any aProps
2354 = uno::makeAny(
2355 beans::PropertyValue(
2356 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2357 "Uri")),
2358 -1,
2359 uno::makeAny( rInfo.SourceURL ),
2360 beans::PropertyState_DIRECT_VALUE));
2361 ucbhelper::cancelCommandExecution(
2362 ucb::IOErrorCode_CANT_WRITE,
2363 uno::Sequence< uno::Any >(&aProps, 1),
2364 xEnv,
2365 rtl::OUString::createFromAscii(
2366 "Cannot remove additional properties of source object!" ),
2367 this );
2368 // Unreachable
2369 }
2370
2371 } // rInfo.MoveData
2372 }
2373
2374 //=========================================================================
2375 //static
hasData(ContentProvider * pProvider,const Uri & rUri)2376 bool Content::hasData( ContentProvider* pProvider, const Uri & rUri )
2377 {
2378 if ( rUri.isRoot() )
2379 {
2380 return true; // root has no storage
2381 }
2382 else if ( rUri.isDocument() )
2383 {
2384 uno::Reference< embed::XStorage > xStorage
2385 = pProvider->queryStorage( rUri.getUri(), READ );
2386 return xStorage.is();
2387 }
2388 else
2389 {
2390 // folder or stream
2391
2392 // Ask parent storage. In case that rUri describes a stream,
2393 // ContentProvider::queryStorage( rUri ) would return null.
2394
2395 uno::Reference< embed::XStorage > xStorage
2396 = pProvider->queryStorage( rUri.getParentUri(), READ );
2397
2398 if ( !xStorage.is() )
2399 return false;
2400
2401 uno::Reference< container::XNameAccess > xParentNA(
2402 xStorage, uno::UNO_QUERY );
2403
2404 OSL_ENSURE( xParentNA.is(), "Got no css.container.XNameAccess!" );
2405
2406 return xParentNA->hasByName( rUri.getDecodedName() );
2407 }
2408 }
2409
2410 //=========================================================================
2411 //static
loadData(ContentProvider * pProvider,const Uri & rUri,ContentProperties & rProps)2412 bool Content::loadData( ContentProvider* pProvider,
2413 const Uri & rUri,
2414 ContentProperties& rProps )
2415 {
2416 if ( rUri.isRoot() ) // root has no storage, but can always be created
2417 {
2418 rProps
2419 = ContentProperties(
2420 ROOT, pProvider->queryStorageTitle( rUri.getUri() ) );
2421 }
2422 else if ( rUri.isDocument() ) // document must have storage
2423 {
2424 uno::Reference< embed::XStorage > xStorage
2425 = pProvider->queryStorage( rUri.getUri(), READ );
2426
2427 if ( !xStorage.is() )
2428 return false;
2429
2430 rProps
2431 = ContentProperties(
2432 DOCUMENT, pProvider->queryStorageTitle( rUri.getUri() ) );
2433 }
2434 else // stream or folder; stream has no storage; folder has storage
2435 {
2436 uno::Reference< embed::XStorage > xStorage
2437 = pProvider->queryStorage( rUri.getParentUri(), READ );
2438
2439 if ( !xStorage.is() )
2440 return false;
2441
2442 // Check whether exists at all, is stream or folder
2443 try
2444 {
2445 // return: true -> folder
2446 // return: false -> stream
2447 // NoSuchElementException -> neither folder nor stream
2448 bool bIsFolder
2449 = xStorage->isStorageElement( rUri.getDecodedName() );
2450
2451 rProps
2452 = ContentProperties(
2453 bIsFolder ? FOLDER : STREAM,
2454 pProvider->queryStorageTitle( rUri.getUri() ) );
2455 }
2456 catch ( container::NoSuchElementException const & )
2457 {
2458 // there is no element with such name
2459 //OSL_ENSURE( false, "Caught NoSuchElementException!" );
2460 return false;
2461 }
2462 catch ( lang::IllegalArgumentException const & )
2463 {
2464 // an illegal argument is provided
2465 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2466 return false;
2467 }
2468 catch ( embed::InvalidStorageException const & )
2469 {
2470 // this storage is in invalid state for any reason
2471 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2472 return false;
2473 }
2474 }
2475 return true;
2476 }
2477
2478 //=========================================================================
storeData(const uno::Reference<io::XInputStream> & xData,const uno::Reference<ucb::XCommandEnvironment> & xEnv)2479 bool Content::storeData( const uno::Reference< io::XInputStream >& xData,
2480 const uno::Reference<
2481 ucb::XCommandEnvironment >& xEnv )
2482 throw ( ucb::CommandFailedException,
2483 task::DocumentPasswordRequest )
2484 {
2485 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2486
2487 ContentType eType = m_aProps.getType();
2488 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2489 {
2490 OSL_ENSURE( false, "storeData not supported by root and documents!" );
2491 return false;
2492 }
2493
2494 Uri aUri( m_xIdentifier->getContentIdentifier() );
2495
2496 if ( eType == FOLDER )
2497 {
2498 uno::Reference< embed::XStorage > xStorage
2499 = m_pProvider->queryStorage( aUri.getUri(), READ_WRITE_CREATE );
2500
2501 if ( !xStorage.is() )
2502 return false;
2503
2504 uno::Reference< beans::XPropertySet > xPropSet(
2505 xStorage, uno::UNO_QUERY );
2506 OSL_ENSURE( xPropSet.is(),
2507 "Content::storeData - Got no XPropertySet interface!" );
2508 if ( !xPropSet.is() )
2509 return false;
2510
2511 try
2512 {
2513 // According to MBA, if no mediatype is set, folder and all
2514 // its contents will be lost on save of the document!!!
2515 xPropSet->setPropertyValue(
2516 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
2517 uno::makeAny(
2518 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2519 // @@@ better mediatype
2520 "application/binary" ) ) ) );
2521 }
2522 catch ( beans::UnknownPropertyException const & )
2523 {
2524 OSL_ENSURE( false, "Property MediaType not supported!" );
2525 return false;
2526 }
2527 catch ( beans::PropertyVetoException const & )
2528 {
2529 OSL_ENSURE( false, "Caught PropertyVetoException!" );
2530 return false;
2531 }
2532 catch ( lang::IllegalArgumentException const & )
2533 {
2534 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2535 return false;
2536 }
2537 catch ( lang::WrappedTargetException const & )
2538 {
2539 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2540 return false;
2541 }
2542
2543 if ( !commitStorage( xStorage ) )
2544 return false;
2545 }
2546 else if ( eType == STREAM )
2547 {
2548 // stream
2549
2550 // Important: Parent storage and output stream must be kept alive until
2551 // changes have been committed!
2552 uno::Reference< embed::XStorage > xStorage
2553 = m_pProvider->queryStorage(
2554 aUri.getParentUri(), READ_WRITE_CREATE );
2555 uno::Reference< io::XOutputStream > xOut;
2556
2557 if ( !xStorage.is() )
2558 return false;
2559
2560 if ( xData.is() )
2561 {
2562 // May throw CommandFailedException, DocumentPasswordRequest!
2563 xOut = getTruncatedOutputStream( xEnv );
2564
2565 OSL_ENSURE( xOut.is(), "No target data stream!" );
2566
2567 try
2568 {
2569 uno::Sequence< sal_Int8 > aBuffer;
2570 sal_Int32 nRead = xData->readSomeBytes( aBuffer, 65536 );
2571
2572 while ( nRead > 0 )
2573 {
2574 aBuffer.realloc( nRead );
2575 xOut->writeBytes( aBuffer );
2576 aBuffer.realloc( 0 );
2577 nRead = xData->readSomeBytes( aBuffer, 65536 );
2578 }
2579
2580 closeOutputStream( xOut );
2581 }
2582 catch ( io::NotConnectedException const & )
2583 {
2584 // readSomeBytes, writeBytes
2585 OSL_ENSURE( false, "Caught NotConnectedException!" );
2586 closeOutputStream( xOut );
2587 return false;
2588 }
2589 catch ( io::BufferSizeExceededException const & )
2590 {
2591 // readSomeBytes, writeBytes
2592 OSL_ENSURE( false, "Caught BufferSizeExceededException!" );
2593 closeOutputStream( xOut );
2594 return false;
2595 }
2596 catch ( io::IOException const & )
2597 {
2598 // readSomeBytes, writeBytes
2599 OSL_ENSURE( false, "Caught IOException!" );
2600 closeOutputStream( xOut );
2601 return false;
2602 }
2603 catch ( ... )
2604 {
2605 closeOutputStream( xOut );
2606 throw;
2607 }
2608 }
2609
2610 // Commit changes.
2611 if ( !commitStorage( xStorage ) )
2612 return false;
2613 }
2614 else
2615 {
2616 OSL_ENSURE( false, "Unknown content type!" );
2617 return false;
2618 }
2619 return true;
2620 }
2621
2622 //=========================================================================
renameData(const uno::Reference<ucb::XContentIdentifier> & xOldId,const uno::Reference<ucb::XContentIdentifier> & xNewId)2623 bool Content::renameData(
2624 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2625 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2626 {
2627 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2628
2629 ContentType eType = m_aProps.getType();
2630 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2631 {
2632 OSL_ENSURE( false, "renameData not supported by root and documents!" );
2633 return false;
2634 }
2635
2636 Uri aOldUri( xOldId->getContentIdentifier() );
2637 uno::Reference< embed::XStorage > xStorage
2638 = m_pProvider->queryStorage(
2639 aOldUri.getParentUri(), READ_WRITE_NOCREATE );
2640
2641 if ( !xStorage.is() )
2642 return false;
2643
2644 try
2645 {
2646 Uri aNewUri( xNewId->getContentIdentifier() );
2647 xStorage->renameElement(
2648 aOldUri.getDecodedName(), aNewUri.getDecodedName() );
2649 }
2650 catch ( embed::InvalidStorageException const & )
2651 {
2652 // this storage is in invalid state for eny reason
2653 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2654 return false;
2655 }
2656 catch ( lang::IllegalArgumentException const & )
2657 {
2658 // an illegal argument is provided
2659 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2660 return false;
2661 }
2662 catch ( container::NoSuchElementException const & )
2663 {
2664 // there is no element with old name in this storage
2665 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2666 return false;
2667 }
2668 catch ( container::ElementExistException const & )
2669 {
2670 // an element with new name already exists in this storage
2671 OSL_ENSURE( false, "Caught ElementExistException!" );
2672 return false;
2673 }
2674 catch ( io::IOException const & )
2675 {
2676 // in case of io errors during renaming
2677 OSL_ENSURE( false, "Caught IOException!" );
2678 return false;
2679 }
2680 catch ( embed::StorageWrappedTargetException const & )
2681 {
2682 // wraps other exceptions
2683 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2684 return false;
2685 }
2686
2687 return commitStorage( xStorage );
2688 }
2689
2690 //=========================================================================
removeData()2691 bool Content::removeData()
2692 {
2693 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2694
2695 ContentType eType = m_aProps.getType();
2696 if ( ( eType == ROOT ) || ( eType == DOCUMENT ) )
2697 {
2698 OSL_ENSURE( false, "removeData not supported by root and documents!" );
2699 return false;
2700 }
2701
2702 Uri aUri( m_xIdentifier->getContentIdentifier() );
2703 uno::Reference< embed::XStorage > xStorage
2704 = m_pProvider->queryStorage(
2705 aUri.getParentUri(), READ_WRITE_NOCREATE );
2706
2707 if ( !xStorage.is() )
2708 return false;
2709
2710 try
2711 {
2712 xStorage->removeElement( aUri.getDecodedName() );
2713 }
2714 catch ( embed::InvalidStorageException const & )
2715 {
2716 // this storage is in invalid state for eny reason
2717 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2718 return false;
2719 }
2720 catch ( lang::IllegalArgumentException const & )
2721 {
2722 // an illegal argument is provided
2723 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2724 return false;
2725 }
2726 catch ( container::NoSuchElementException const & )
2727 {
2728 // there is no element with this name in this storage
2729 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2730 return false;
2731 }
2732 catch ( io::IOException const & )
2733 {
2734 // in case of io errors during renaming
2735 OSL_ENSURE( false, "Caught IOException!" );
2736 return false;
2737 }
2738 catch ( embed::StorageWrappedTargetException const & )
2739 {
2740 // wraps other exceptions
2741 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2742 return false;
2743 }
2744
2745 return commitStorage( xStorage );
2746 }
2747
2748 //=========================================================================
copyData(const Uri & rSourceUri,const rtl::OUString & rNewName)2749 bool Content::copyData( const Uri & rSourceUri, const rtl::OUString & rNewName )
2750 {
2751 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2752
2753 ContentType eType = m_aProps.getType();
2754 if ( ( eType == ROOT ) || ( eType == STREAM ) )
2755 {
2756 OSL_ENSURE( false, "copyData not supported by root and streams!" );
2757 return false;
2758 }
2759
2760 Uri aDestUri( m_xIdentifier->getContentIdentifier() );
2761 uno::Reference< embed::XStorage > xDestStorage
2762 = m_pProvider->queryStorage( aDestUri.getUri(), READ_WRITE_NOCREATE );
2763
2764 if ( !xDestStorage.is() )
2765 return false;
2766
2767 uno::Reference< embed::XStorage > xSourceStorage
2768 = m_pProvider->queryStorage( rSourceUri.getParentUri(), READ );
2769
2770 if ( !xSourceStorage.is() )
2771 return false;
2772
2773 try
2774 {
2775 xSourceStorage->copyElementTo( rSourceUri.getDecodedName(),
2776 xDestStorage,
2777 rNewName );
2778 }
2779 catch ( embed::InvalidStorageException const & )
2780 {
2781 // this storage is in invalid state for eny reason
2782 OSL_ENSURE( false, "Caught InvalidStorageException!" );
2783 return false;
2784 }
2785 catch ( lang::IllegalArgumentException const & )
2786 {
2787 // an illegal argument is provided
2788 OSL_ENSURE( false, "Caught IllegalArgumentException!" );
2789 return false;
2790 }
2791 catch ( container::NoSuchElementException const & )
2792 {
2793 // there is no element with this name in this storage
2794 OSL_ENSURE( false, "Caught NoSuchElementException!" );
2795 return false;
2796 }
2797 catch ( container::ElementExistException const & )
2798 {
2799 // there is no element with this name in this storage
2800 OSL_ENSURE( false, "Caught ElementExistException!" );
2801 return false;
2802 }
2803 catch ( io::IOException const & )
2804 {
2805 // in case of io errors during renaming
2806 OSL_ENSURE( false, "Caught IOException!" );
2807 return false;
2808 }
2809 catch ( embed::StorageWrappedTargetException const & )
2810 {
2811 // wraps other exceptions
2812 OSL_ENSURE( false, "Caught StorageWrappedTargetException!" );
2813 return false;
2814 }
2815
2816 return commitStorage( xDestStorage );
2817 }
2818
2819 //=========================================================================
2820 // static
commitStorage(const uno::Reference<embed::XStorage> & xStorage)2821 bool Content::commitStorage( const uno::Reference< embed::XStorage > & xStorage )
2822 {
2823 // Commit changes
2824 uno::Reference< embed::XTransactedObject > xTO( xStorage, uno::UNO_QUERY );
2825
2826 OSL_ENSURE( xTO.is(),
2827 "Required interface css.embed.XTransactedObject missing!" );
2828 try
2829 {
2830 xTO->commit();
2831 }
2832 catch ( io::IOException const & )
2833 {
2834 OSL_ENSURE( false, "Caught IOException!" );
2835 return false;
2836 }
2837 catch ( lang::WrappedTargetException const & )
2838 {
2839 OSL_ENSURE( false, "Caught WrappedTargetException!" );
2840 return false;
2841 }
2842
2843 return true;
2844 }
2845
2846 //=========================================================================
2847 // static
closeOutputStream(const uno::Reference<io::XOutputStream> & xOut)2848 bool Content::closeOutputStream(
2849 const uno::Reference< io::XOutputStream > & xOut )
2850 {
2851 if ( xOut.is() )
2852 {
2853 try
2854 {
2855 xOut->closeOutput();
2856 return true;
2857 }
2858 catch ( io::NotConnectedException const & )
2859 {
2860 OSL_ENSURE( false, "Caught NotConnectedException!" );
2861 }
2862 catch ( io::BufferSizeExceededException const & )
2863 {
2864 OSL_ENSURE( false, "Caught BufferSizeExceededException!" );
2865 }
2866 catch ( io::IOException const & )
2867 {
2868 OSL_ENSURE( false, "Caught IOException!" );
2869 }
2870 }
2871 return false;
2872 }
2873
2874 //=========================================================================
obtainPassword(const rtl::OUString & rName,task::PasswordRequestMode eMode,const uno::Reference<ucb::XCommandEnvironment> & xEnv)2875 static rtl::OUString obtainPassword(
2876 const rtl::OUString & rName,
2877 task::PasswordRequestMode eMode,
2878 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2879 throw ( ucb::CommandFailedException,
2880 task::DocumentPasswordRequest )
2881 {
2882 rtl::Reference< DocumentPasswordRequest > xRequest
2883 = new DocumentPasswordRequest( eMode, rName );
2884
2885 if ( xEnv.is() )
2886 {
2887 uno::Reference< task::XInteractionHandler > xIH
2888 = xEnv->getInteractionHandler();
2889 if ( xIH.is() )
2890 {
2891 xIH->handle( xRequest.get() );
2892
2893 rtl::Reference< ucbhelper::InteractionContinuation > xSelection
2894 = xRequest->getSelection();
2895
2896 if ( xSelection.is() )
2897 {
2898 // Handler handled the request.
2899 uno::Reference< task::XInteractionAbort > xAbort(
2900 xSelection.get(), uno::UNO_QUERY );
2901 if ( xAbort.is() )
2902 {
2903 throw ucb::CommandFailedException(
2904 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2905 "Abort requested by Interaction Handler." ) ),
2906 uno::Reference< uno::XInterface >(),
2907 xRequest->getRequest() );
2908 }
2909
2910 uno::Reference< task::XInteractionPassword > xPassword(
2911 xSelection.get(), uno::UNO_QUERY );
2912 if ( xPassword.is() )
2913 {
2914 return xPassword->getPassword();
2915 }
2916
2917 // Unknown selection. Should never happen.
2918 throw ucb::CommandFailedException(
2919 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
2920 "Interaction Handler selected unknown continuation!" ) ),
2921 uno::Reference< uno::XInterface >(),
2922 xRequest->getRequest() );
2923 }
2924 }
2925 }
2926
2927 // No IH or IH did not handle exception.
2928 task::DocumentPasswordRequest aRequest;
2929 xRequest->getRequest() >>= aRequest;
2930 throw aRequest;
2931 }
2932
2933 //=========================================================================
getInputStream(const uno::Reference<ucb::XCommandEnvironment> & xEnv)2934 uno::Reference< io::XInputStream > Content::getInputStream(
2935 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2936 throw ( ucb::CommandFailedException,
2937 task::DocumentPasswordRequest )
2938 {
2939 rtl::OUString aUri;
2940 rtl::OUString aPassword;
2941 bool bPasswordRequested = false;
2942
2943 {
2944 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2945
2946 OSL_ENSURE( m_aProps.getType() == STREAM,
2947 "Content::getInputStream - content is no stream!" );
2948
2949 aUri = Uri( m_xIdentifier->getContentIdentifier() ).getUri();
2950 }
2951
2952 for ( ;; )
2953 {
2954 try
2955 {
2956 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2957 return uno::Reference< io::XInputStream >(
2958 m_pProvider->queryInputStream( aUri, aPassword ) );
2959 }
2960 catch ( packages::WrongPasswordException const & )
2961 {
2962 // Obtain (new) password.
2963 aPassword
2964 = obtainPassword( aUri, /* @@@ find better title */
2965 bPasswordRequested
2966 ? task::PasswordRequestMode_PASSWORD_REENTER
2967 : task::PasswordRequestMode_PASSWORD_ENTER,
2968 xEnv );
2969 bPasswordRequested = true;
2970 }
2971 }
2972 }
2973
2974 //=========================================================================
lcl_getTruncatedOutputStream(const rtl::OUString & rUri,ContentProvider * pProvider,const uno::Reference<ucb::XCommandEnvironment> & xEnv)2975 static uno::Reference< io::XOutputStream > lcl_getTruncatedOutputStream(
2976 const rtl::OUString & rUri,
2977 ContentProvider * pProvider,
2978 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
2979 throw ( ucb::CommandFailedException,
2980 task::DocumentPasswordRequest )
2981 {
2982 rtl::OUString aPassword;
2983 bool bPasswordRequested = false;
2984 for ( ;; )
2985 {
2986 try
2987 {
2988 return uno::Reference< io::XOutputStream >(
2989 pProvider->queryOutputStream(
2990 rUri, aPassword, true /* truncate */ ) );
2991 }
2992 catch ( packages::WrongPasswordException const & )
2993 {
2994 // Obtain (new) password.
2995 aPassword
2996 = obtainPassword( rUri, /* @@@ find better title */
2997 bPasswordRequested
2998 ? task::PasswordRequestMode_PASSWORD_REENTER
2999 : task::PasswordRequestMode_PASSWORD_ENTER,
3000 xEnv );
3001 bPasswordRequested = true;
3002 }
3003 }
3004 }
3005
3006 //=========================================================================
getTruncatedOutputStream(const uno::Reference<ucb::XCommandEnvironment> & xEnv)3007 uno::Reference< io::XOutputStream > Content::getTruncatedOutputStream(
3008 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
3009 throw ( ucb::CommandFailedException,
3010 task::DocumentPasswordRequest )
3011 {
3012 OSL_ENSURE( m_aProps.getType() == STREAM,
3013 "Content::getTruncatedOutputStream - content is no stream!" );
3014
3015 return lcl_getTruncatedOutputStream(
3016 Uri( m_xIdentifier->getContentIdentifier() ).getUri(),
3017 m_pProvider,
3018 xEnv );
3019 }
3020
3021 //=========================================================================
getStream(const uno::Reference<ucb::XCommandEnvironment> & xEnv)3022 uno::Reference< io::XStream > Content::getStream(
3023 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
3024 throw ( ucb::CommandFailedException,
3025 task::DocumentPasswordRequest )
3026 {
3027 osl::Guard< osl::Mutex > aGuard( m_aMutex );
3028
3029 OSL_ENSURE( m_aProps.getType() == STREAM,
3030 "Content::getStream - content is no stream!" );
3031
3032 rtl::OUString aUri( Uri( m_xIdentifier->getContentIdentifier() ).getUri() );
3033 rtl::OUString aPassword;
3034 bool bPasswordRequested = false;
3035 for ( ;; )
3036 {
3037 try
3038 {
3039 return uno::Reference< io::XStream >(
3040 m_pProvider->queryStream(
3041 aUri, aPassword, false /* no truncate */ ) );
3042 }
3043 catch ( packages::WrongPasswordException const & )
3044 {
3045 // Obtain (new) password.
3046 aPassword
3047 = obtainPassword( aUri, /* @@@ find better title */
3048 bPasswordRequested
3049 ? task::PasswordRequestMode_PASSWORD_REENTER
3050 : task::PasswordRequestMode_PASSWORD_ENTER,
3051 xEnv );
3052 bPasswordRequested = true;
3053 }
3054 }
3055 }
3056
3057 //=========================================================================
3058 //=========================================================================
3059 //
3060 // ContentProperties Implementation.
3061 //
3062 //=========================================================================
3063 //=========================================================================
3064
3065 uno::Sequence< ucb::ContentInfo >
getCreatableContentsInfo() const3066 ContentProperties::getCreatableContentsInfo() const
3067 {
3068 if ( isContentCreator() )
3069 {
3070 uno::Sequence< beans::Property > aProps( 1 );
3071 aProps.getArray()[ 0 ] = beans::Property(
3072 rtl::OUString::createFromAscii( "Title" ),
3073 -1,
3074 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
3075 beans::PropertyAttribute::BOUND );
3076
3077 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
3078 if ( getType() == DOCUMENT )
3079 {
3080 // streams cannot be created as direct children of document root
3081 uno::Sequence< ucb::ContentInfo > aSeq( 1 );
3082
3083 // Folder.
3084 aSeq.getArray()[ 0 ].Type
3085 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE );
3086 aSeq.getArray()[ 0 ].Attributes
3087 = ucb::ContentInfoAttribute::KIND_FOLDER;
3088 aSeq.getArray()[ 0 ].Properties = aProps;
3089
3090 return aSeq;
3091 }
3092 else
3093 {
3094 #endif
3095 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
3096
3097 // Folder.
3098 aSeq.getArray()[ 0 ].Type
3099 = rtl::OUString::createFromAscii( TDOC_FOLDER_CONTENT_TYPE );
3100 aSeq.getArray()[ 0 ].Attributes
3101 = ucb::ContentInfoAttribute::KIND_FOLDER;
3102 aSeq.getArray()[ 0 ].Properties = aProps;
3103
3104 // Stream.
3105 aSeq.getArray()[ 1 ].Type
3106 = rtl::OUString::createFromAscii( TDOC_STREAM_CONTENT_TYPE );
3107 aSeq.getArray()[ 1 ].Attributes
3108 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
3109 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
3110 aSeq.getArray()[ 1 ].Properties = aProps;
3111
3112 return aSeq;
3113 #ifdef NO_STREAM_CREATION_WITHIN_DOCUMENT_ROOT
3114 }
3115 #endif
3116 }
3117 else
3118 {
3119 OSL_ENSURE( sal_False,
3120 "getCreatableContentsInfo called on non-contentcreator "
3121 "object!" );
3122
3123 return uno::Sequence< ucb::ContentInfo >( 0 );
3124 }
3125 }
3126
3127 //=========================================================================
isContentCreator() const3128 bool ContentProperties::isContentCreator() const
3129 {
3130 return ( getType() == FOLDER ) || ( getType() == DOCUMENT );
3131 }
3132