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