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