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