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