Update ooo320-m1
[ooovba.git] / ucb / source / ucp / package / pkgcontent.cxx
blobeafac3d76908621b4c0e8423b2ef067109f37048
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: pkgcontent.cxx,v $
10 * $Revision: 1.59 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
35 TODO
36 **************************************************************************
37 *************************************************************************/
38 #include <osl/diagnose.h>
40 #include "osl/doublecheckedlocking.h"
41 #include <rtl/ustring.h>
42 #include <rtl/ustring.hxx>
43 #include <com/sun/star/beans/PropertyAttribute.hpp>
44 #include <com/sun/star/beans/PropertyState.hpp>
45 #include <com/sun/star/beans/PropertyValue.hpp>
46 #include <com/sun/star/beans/XPropertyAccess.hpp>
47 #include <com/sun/star/container/XEnumerationAccess.hpp>
48 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
49 #include <com/sun/star/container/XNameContainer.hpp>
50 #include <com/sun/star/container/XNamed.hpp>
51 #include <com/sun/star/io/XActiveDataSink.hpp>
52 #include <com/sun/star/io/XInputStream.hpp>
53 #include <com/sun/star/io/XOutputStream.hpp>
54 #include <com/sun/star/lang/IllegalAccessException.hpp>
55 #include <com/sun/star/sdbc/XRow.hpp>
56 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
57 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
58 #ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_
59 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
60 #endif
61 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
62 #include <com/sun/star/ucb/NameClash.hpp>
63 #include <com/sun/star/ucb/NameClashException.hpp>
64 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
65 #include <com/sun/star/ucb/OpenMode.hpp>
66 #include <com/sun/star/ucb/TransferInfo.hpp>
67 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
68 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
69 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
70 #include <com/sun/star/ucb/XCommandInfo.hpp>
71 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
72 #include <com/sun/star/util/XChangesBatch.hpp>
73 #include <com/sun/star/uno/Any.hxx>
74 #include <com/sun/star/uno/Sequence.hxx>
75 #include <ucbhelper/contentidentifier.hxx>
76 #include <ucbhelper/propertyvalueset.hxx>
77 #include <ucbhelper/cancelcommandexecution.hxx>
78 #include "pkgcontent.hxx"
79 #include "pkgprovider.hxx"
80 #include "pkgresultset.hxx"
82 #include "../inc/urihelper.hxx"
84 using namespace com::sun::star;
85 using namespace package_ucp;
87 #define NONE_MODIFIED sal_uInt32( 0x00 )
88 #define MEDIATYPE_MODIFIED sal_uInt32( 0x01 )
89 #define COMPRESSED_MODIFIED sal_uInt32( 0x02 )
90 #define ENCRYPTED_MODIFIED sal_uInt32( 0x04 )
91 #define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 )
93 //=========================================================================
94 //=========================================================================
96 // ContentProperties Implementation.
98 //=========================================================================
99 //=========================================================================
101 ContentProperties::ContentProperties( const rtl::OUString& rContentType )
102 : aContentType( rContentType ),
103 nSize( 0 ),
104 bCompressed( sal_True ),
105 bEncrypted( sal_False ),
106 bHasEncryptedEntries( sal_False )
108 bIsFolder = rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PACKAGE_FOLDER_CONTENT_TYPE ) )
109 || rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_FOLDER_CONTENT_TYPE ) );
110 bIsDocument = !bIsFolder;
112 OSL_ENSURE( bIsFolder ||
113 rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PACKAGE_STREAM_CONTENT_TYPE ) ) ||
114 rContentType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( PACKAGE_ZIP_STREAM_CONTENT_TYPE ) ),
115 "ContentProperties::ContentProperties - Unknown type!" );
118 //=========================================================================
119 //=========================================================================
121 // Content Implementation.
123 //=========================================================================
124 //=========================================================================
126 // static ( "virtual" ctor )
127 Content* Content::create(
128 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
129 ContentProvider* pProvider,
130 const uno::Reference< ucb::XContentIdentifier >& Identifier )
132 rtl::OUString aURL = Identifier->getContentIdentifier();
133 PackageUri aURI( aURL );
134 ContentProperties aProps;
135 uno::Reference< container::XHierarchicalNameAccess > xPackage;
137 if ( loadData( pProvider, aURI, aProps, xPackage ) )
139 // resource exists
141 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
142 if ( ( nLastSlash + 1 ) == aURL.getLength() )
144 // Client explicitely requested a folder!
145 if ( !aProps.bIsFolder )
146 return 0;
149 uno::Reference< ucb::XContentIdentifier > xId
150 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
151 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aProps );
153 else
155 // resource doesn't exist
157 sal_Bool bFolder = sal_False;
159 // Guess type according to URI.
160 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
161 if ( ( nLastSlash + 1 ) == aURL.getLength() )
162 bFolder = sal_True;
164 uno::Reference< ucb::XContentIdentifier > xId
165 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
167 ucb::ContentInfo aInfo;
168 if ( bFolder || aURI.isRootFolder() )
169 aInfo.Type = GetContentType( aURI.getScheme(), sal_True );
170 else
171 aInfo.Type = GetContentType( aURI.getScheme(), sal_False );
173 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aInfo );
177 //=========================================================================
178 // static ( "virtual" ctor )
179 Content* Content::create(
180 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
181 ContentProvider* pProvider,
182 const uno::Reference< ucb::XContentIdentifier >& Identifier,
183 const ucb::ContentInfo& Info )
185 if ( !Info.Type.getLength() )
186 return 0;
188 PackageUri aURI( Identifier->getContentIdentifier() );
190 if ( !Info.Type.equalsIgnoreAsciiCase(
191 GetContentType( aURI.getScheme(), sal_True ) ) &&
192 !Info.Type.equalsIgnoreAsciiCase(
193 GetContentType( aURI.getScheme(), sal_False ) ) )
194 return 0;
196 uno::Reference< container::XHierarchicalNameAccess > xPackage;
198 #if 0
199 // Fail, if content does exist.
200 if ( hasData( pProvider, aURI, xPackage ) )
201 return 0;
202 #else
203 xPackage = pProvider->createPackage( aURI.getPackage(), aURI.getParam() );
204 #endif
206 uno::Reference< ucb::XContentIdentifier > xId
207 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
208 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, Info );
211 //=========================================================================
212 // static
213 ::rtl::OUString Content::GetContentType(
214 const ::rtl::OUString& aScheme, sal_Bool bFolder )
216 return ( rtl::OUString::createFromAscii( "application/" )
217 + aScheme
218 + ( bFolder
219 ? rtl::OUString::createFromAscii( "-folder" )
220 : rtl::OUString::createFromAscii( "-stream" ) ) );
223 //=========================================================================
224 Content::Content(
225 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
226 ContentProvider* pProvider,
227 const uno::Reference< ucb::XContentIdentifier >& Identifier,
228 const uno::Reference< container::XHierarchicalNameAccess > & Package,
229 const PackageUri& rUri,
230 const ContentProperties& rProps )
231 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
232 m_aUri( rUri ),
233 m_aProps( rProps ),
234 m_eState( PERSISTENT ),
235 m_xPackage( Package ),
236 m_pProvider( pProvider ),
237 m_nModifiedProps( NONE_MODIFIED )
241 //=========================================================================
242 Content::Content(
243 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
244 ContentProvider* pProvider,
245 const uno::Reference< ucb::XContentIdentifier >& Identifier,
246 const uno::Reference< container::XHierarchicalNameAccess > & Package,
247 const PackageUri& rUri,
248 const ucb::ContentInfo& Info )
249 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
250 m_aUri( rUri ),
251 m_aProps( Info.Type ),
252 m_eState( TRANSIENT ),
253 m_xPackage( Package ),
254 m_pProvider( pProvider ),
255 m_nModifiedProps( NONE_MODIFIED )
259 //=========================================================================
260 // virtual
261 Content::~Content()
265 //=========================================================================
267 // XInterface methods.
269 //=========================================================================
271 // virtual
272 void SAL_CALL Content::acquire()
273 throw( )
275 ContentImplHelper::acquire();
278 //=========================================================================
279 // virtual
280 void SAL_CALL Content::release()
281 throw( )
283 ContentImplHelper::release();
286 //=========================================================================
287 // virtual
288 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
289 throw ( uno::RuntimeException )
291 uno::Any aRet;
293 if ( isFolder() )
294 aRet = cppu::queryInterface(
295 rType, static_cast< ucb::XContentCreator * >( this ) );
297 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
300 //=========================================================================
302 // XTypeProvider methods.
304 //=========================================================================
306 XTYPEPROVIDER_COMMON_IMPL( Content );
308 //=========================================================================
309 // virtual
310 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
311 throw( uno::RuntimeException )
313 cppu::OTypeCollection * pCollection = 0;
315 if ( isFolder() )
317 static cppu::OTypeCollection* pFolderTypes = 0;
319 pCollection = pFolderTypes;
320 if ( !pCollection )
322 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
324 pCollection = pFolderTypes;
325 if ( !pCollection )
327 static cppu::OTypeCollection aCollection(
328 CPPU_TYPE_REF( lang::XTypeProvider ),
329 CPPU_TYPE_REF( lang::XServiceInfo ),
330 CPPU_TYPE_REF( lang::XComponent ),
331 CPPU_TYPE_REF( ucb::XContent ),
332 CPPU_TYPE_REF( ucb::XCommandProcessor ),
333 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
334 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
335 CPPU_TYPE_REF( beans::XPropertyContainer ),
336 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
337 CPPU_TYPE_REF( container::XChild ),
338 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
339 pCollection = &aCollection;
340 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
341 pFolderTypes = pCollection;
344 else {
345 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
348 else
350 static cppu::OTypeCollection* pDocumentTypes = 0;
352 pCollection = pDocumentTypes;
353 if ( !pCollection )
355 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
357 pCollection = pDocumentTypes;
358 if ( !pCollection )
360 static cppu::OTypeCollection aCollection(
361 CPPU_TYPE_REF( lang::XTypeProvider ),
362 CPPU_TYPE_REF( lang::XServiceInfo ),
363 CPPU_TYPE_REF( lang::XComponent ),
364 CPPU_TYPE_REF( ucb::XContent ),
365 CPPU_TYPE_REF( ucb::XCommandProcessor ),
366 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
367 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
368 CPPU_TYPE_REF( beans::XPropertyContainer ),
369 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
370 CPPU_TYPE_REF( container::XChild ) );
371 pCollection = &aCollection;
372 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
373 pDocumentTypes = pCollection;
376 else {
377 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
381 return (*pCollection).getTypes();
384 //=========================================================================
386 // XServiceInfo methods.
388 //=========================================================================
390 // virtual
391 rtl::OUString SAL_CALL Content::getImplementationName()
392 throw( uno::RuntimeException )
394 return rtl::OUString::createFromAscii(
395 "com.sun.star.comp.ucb.PackageContent" );
398 //=========================================================================
399 // virtual
400 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
401 throw( uno::RuntimeException )
403 uno::Sequence< rtl::OUString > aSNS( 1 );
404 if ( isFolder() )
405 aSNS.getArray()[ 0 ]
406 = rtl::OUString::createFromAscii(
407 PACKAGE_FOLDER_CONTENT_SERVICE_NAME );
408 else
409 aSNS.getArray()[ 0 ]
410 = rtl::OUString::createFromAscii(
411 PACKAGE_STREAM_CONTENT_SERVICE_NAME );
413 return aSNS;
416 //=========================================================================
418 // XContent methods.
420 //=========================================================================
422 // virtual
423 rtl::OUString SAL_CALL Content::getContentType()
424 throw( uno::RuntimeException )
426 return m_aProps.aContentType;
429 //=========================================================================
431 // XCommandProcessor methods.
433 //=========================================================================
435 // virtual
436 uno::Any SAL_CALL Content::execute(
437 const ucb::Command& aCommand,
438 sal_Int32 /*CommandId*/,
439 const uno::Reference< ucb::XCommandEnvironment >& Environment )
440 throw( uno::Exception,
441 ucb::CommandAbortedException,
442 uno::RuntimeException )
444 uno::Any aRet;
446 if ( aCommand.Name.equalsAsciiL(
447 RTL_CONSTASCII_STRINGPARAM( "getPropertyValues" ) ) )
449 //////////////////////////////////////////////////////////////////
450 // getPropertyValues
451 //////////////////////////////////////////////////////////////////
453 uno::Sequence< beans::Property > Properties;
454 if ( !( aCommand.Argument >>= Properties ) )
456 ucbhelper::cancelCommandExecution(
457 uno::makeAny( lang::IllegalArgumentException(
458 rtl::OUString::createFromAscii(
459 "Wrong argument type!" ),
460 static_cast< cppu::OWeakObject * >( this ),
461 -1 ) ),
462 Environment );
463 // Unreachable
466 aRet <<= getPropertyValues( Properties );
468 else if ( aCommand.Name.equalsAsciiL(
469 RTL_CONSTASCII_STRINGPARAM( "setPropertyValues" ) ) )
471 //////////////////////////////////////////////////////////////////
472 // setPropertyValues
473 //////////////////////////////////////////////////////////////////
475 uno::Sequence< beans::PropertyValue > aProperties;
476 if ( !( aCommand.Argument >>= aProperties ) )
478 ucbhelper::cancelCommandExecution(
479 uno::makeAny( lang::IllegalArgumentException(
480 rtl::OUString::createFromAscii(
481 "Wrong argument type!" ),
482 static_cast< cppu::OWeakObject * >( this ),
483 -1 ) ),
484 Environment );
485 // Unreachable
488 if ( !aProperties.getLength() )
490 ucbhelper::cancelCommandExecution(
491 uno::makeAny( lang::IllegalArgumentException(
492 rtl::OUString::createFromAscii(
493 "No properties!" ),
494 static_cast< cppu::OWeakObject * >( this ),
495 -1 ) ),
496 Environment );
497 // Unreachable
500 aRet <<= setPropertyValues( aProperties, Environment );
502 else if ( aCommand.Name.equalsAsciiL(
503 RTL_CONSTASCII_STRINGPARAM( "getPropertySetInfo" ) ) )
505 //////////////////////////////////////////////////////////////////
506 // getPropertySetInfo
507 //////////////////////////////////////////////////////////////////
509 // Note: Implemented by base class.
510 aRet <<= getPropertySetInfo( Environment );
512 else if ( aCommand.Name.equalsAsciiL(
513 RTL_CONSTASCII_STRINGPARAM( "getCommandInfo" ) ) )
515 //////////////////////////////////////////////////////////////////
516 // getCommandInfo
517 //////////////////////////////////////////////////////////////////
519 // Note: Implemented by base class.
520 aRet <<= getCommandInfo( Environment );
522 else if ( aCommand.Name.equalsAsciiL(
523 RTL_CONSTASCII_STRINGPARAM( "open" ) ) )
525 //////////////////////////////////////////////////////////////////
526 // open
527 //////////////////////////////////////////////////////////////////
529 ucb::OpenCommandArgument2 aOpenCommand;
530 if ( !( aCommand.Argument >>= aOpenCommand ) )
532 ucbhelper::cancelCommandExecution(
533 uno::makeAny( lang::IllegalArgumentException(
534 rtl::OUString::createFromAscii(
535 "Wrong argument type!" ),
536 static_cast< cppu::OWeakObject * >( this ),
537 -1 ) ),
538 Environment );
539 // Unreachable
542 aRet = open( aOpenCommand, Environment );
544 else if ( !m_aUri.isRootFolder()
545 && aCommand.Name.equalsAsciiL(
546 RTL_CONSTASCII_STRINGPARAM( "insert" ) ) )
548 //////////////////////////////////////////////////////////////////
549 // insert
550 //////////////////////////////////////////////////////////////////
552 ucb::InsertCommandArgument aArg;
553 if ( !( aCommand.Argument >>= aArg ) )
555 ucbhelper::cancelCommandExecution(
556 uno::makeAny( lang::IllegalArgumentException(
557 rtl::OUString::createFromAscii(
558 "Wrong argument type!" ),
559 static_cast< cppu::OWeakObject * >( this ),
560 -1 ) ),
561 Environment );
562 // Unreachable
565 sal_Int32 nNameClash = aArg.ReplaceExisting
566 ? ucb::NameClash::OVERWRITE
567 : ucb::NameClash::ERROR;
568 insert( aArg.Data, nNameClash, Environment );
570 else if ( !m_aUri.isRootFolder()
571 && aCommand.Name.equalsAsciiL(
572 RTL_CONSTASCII_STRINGPARAM( "delete" ) ) )
574 //////////////////////////////////////////////////////////////////
575 // delete
576 //////////////////////////////////////////////////////////////////
578 sal_Bool bDeletePhysical = sal_False;
579 aCommand.Argument >>= bDeletePhysical;
580 destroy( bDeletePhysical, Environment );
582 // Remove own and all children's persistent data.
583 if ( !removeData() )
585 uno::Any aProps
586 = uno::makeAny(
587 beans::PropertyValue(
588 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
589 "Uri")),
591 uno::makeAny(m_xIdentifier->
592 getContentIdentifier()),
593 beans::PropertyState_DIRECT_VALUE));
594 ucbhelper::cancelCommandExecution(
595 ucb::IOErrorCode_CANT_WRITE,
596 uno::Sequence< uno::Any >(&aProps, 1),
597 Environment,
598 rtl::OUString::createFromAscii(
599 "Cannot remove persistent data!" ),
600 this );
601 // Unreachable
604 // Remove own and all children's Additional Core Properties.
605 removeAdditionalPropertySet( sal_True );
607 else if ( aCommand.Name.equalsAsciiL(
608 RTL_CONSTASCII_STRINGPARAM( "transfer" ) ) )
610 //////////////////////////////////////////////////////////////////
611 // transfer
612 // ( Not available at stream objects )
613 //////////////////////////////////////////////////////////////////
615 ucb::TransferInfo aInfo;
616 if ( !( aCommand.Argument >>= aInfo ) )
618 ucbhelper::cancelCommandExecution(
619 uno::makeAny( lang::IllegalArgumentException(
620 rtl::OUString::createFromAscii(
621 "Wrong argument type!" ),
622 static_cast< cppu::OWeakObject * >( this ),
623 -1 ) ),
624 Environment );
625 // Unreachable
628 transfer( aInfo, Environment );
630 else if ( aCommand.Name.equalsAsciiL(
631 RTL_CONSTASCII_STRINGPARAM( "flush" ) ) )
633 //////////////////////////////////////////////////////////////////
634 // flush
635 // ( Not available at stream objects )
636 //////////////////////////////////////////////////////////////////
638 if( !flushData() )
640 uno::Any aProps
641 = uno::makeAny(
642 beans::PropertyValue(
643 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
644 "Uri")),
646 uno::makeAny(m_xIdentifier->
647 getContentIdentifier()),
648 beans::PropertyState_DIRECT_VALUE));
649 ucbhelper::cancelCommandExecution(
650 ucb::IOErrorCode_CANT_WRITE,
651 uno::Sequence< uno::Any >(&aProps, 1),
652 Environment,
653 rtl::OUString::createFromAscii(
654 "Cannot write file to disk!" ),
655 this );
656 // Unreachable
659 else
661 //////////////////////////////////////////////////////////////////
662 // Unsupported command
663 //////////////////////////////////////////////////////////////////
665 ucbhelper::cancelCommandExecution(
666 uno::makeAny( ucb::UnsupportedCommandException(
667 rtl::OUString(),
668 static_cast< cppu::OWeakObject * >( this ) ) ),
669 Environment );
670 // Unreachable
673 return aRet;
676 //=========================================================================
677 // virtual
678 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
679 throw( uno::RuntimeException )
681 // @@@ Implement logic to abort running commands, if this makes
682 // sense for your content.
685 //=========================================================================
687 // XContentCreator methods.
689 //=========================================================================
691 // virtual
692 uno::Sequence< ucb::ContentInfo > SAL_CALL
693 Content::queryCreatableContentsInfo()
694 throw( uno::RuntimeException )
696 if ( isFolder() )
698 osl::Guard< osl::Mutex > aGuard( m_aMutex );
700 uno::Sequence< beans::Property > aProps( 1 );
701 aProps.getArray()[ 0 ] = beans::Property(
702 rtl::OUString::createFromAscii( "Title" ),
704 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
705 beans::PropertyAttribute::BOUND );
707 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
709 // Folder.
710 aSeq.getArray()[ 0 ].Type
711 = GetContentType( m_aUri.getScheme(), sal_True );
712 aSeq.getArray()[ 0 ].Attributes
713 = ucb::ContentInfoAttribute::KIND_FOLDER;
714 aSeq.getArray()[ 0 ].Properties = aProps;
716 // Stream.
717 aSeq.getArray()[ 1 ].Type
718 = GetContentType( m_aUri.getScheme(), sal_False );
719 aSeq.getArray()[ 1 ].Attributes
720 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
721 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
722 aSeq.getArray()[ 1 ].Properties = aProps;
724 return aSeq;
726 else
728 OSL_ENSURE( sal_False,
729 "queryCreatableContentsInfo called on non-folder object!" );
731 return uno::Sequence< ucb::ContentInfo >( 0 );
735 //=========================================================================
736 // virtual
737 uno::Reference< ucb::XContent > SAL_CALL
738 Content::createNewContent( const ucb::ContentInfo& Info )
739 throw( uno::RuntimeException )
741 if ( isFolder() )
743 osl::Guard< osl::Mutex > aGuard( m_aMutex );
745 if ( !Info.Type.getLength() )
746 return uno::Reference< ucb::XContent >();
748 if ( !Info.Type.equalsIgnoreAsciiCase(
749 GetContentType( m_aUri.getScheme(), sal_True ) ) &&
750 !Info.Type.equalsIgnoreAsciiCase(
751 GetContentType( m_aUri.getScheme(), sal_False ) ) )
752 return uno::Reference< ucb::XContent >();
754 rtl::OUString aURL = m_aUri.getUri();
755 aURL += rtl::OUString::createFromAscii( "/" );
757 if ( Info.Type.equalsIgnoreAsciiCase(
758 GetContentType( m_aUri.getScheme(), sal_True ) ) )
759 aURL += rtl::OUString::createFromAscii( "New_Folder" );
760 else
761 aURL += rtl::OUString::createFromAscii( "New_Stream" );
763 uno::Reference< ucb::XContentIdentifier > xId(
764 new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) );
766 return create( m_xSMgr, m_pProvider, xId, Info );
768 else
770 OSL_ENSURE( sal_False,
771 "createNewContent called on non-folder object!" );
772 return uno::Reference< ucb::XContent >();
776 //=========================================================================
778 // Non-interface methods.
780 //=========================================================================
782 // virtual
783 rtl::OUString Content::getParentURL()
785 return m_aUri.getParentUri();
788 //=========================================================================
789 // static
790 uno::Reference< sdbc::XRow > Content::getPropertyValues(
791 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
792 const uno::Sequence< beans::Property >& rProperties,
793 ContentProvider* pProvider,
794 const rtl::OUString& rContentId )
796 ContentProperties aData;
797 uno::Reference< container::XHierarchicalNameAccess > xPackage;
798 if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) )
800 return getPropertyValues( rSMgr,
801 rProperties,
802 aData,
803 rtl::Reference<
804 ::ucbhelper::ContentProviderImplHelper >(
805 pProvider ),
806 rContentId );
808 else
810 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
811 = new ::ucbhelper::PropertyValueSet( rSMgr );
813 sal_Int32 nCount = rProperties.getLength();
814 if ( nCount )
816 const beans::Property* pProps = rProperties.getConstArray();
817 for ( sal_Int32 n = 0; n < nCount; ++n )
818 xRow->appendVoid( pProps[ n ] );
821 return uno::Reference< sdbc::XRow >( xRow.get() );
825 //=========================================================================
826 // static
827 uno::Reference< sdbc::XRow > Content::getPropertyValues(
828 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
829 const uno::Sequence< beans::Property >& rProperties,
830 const ContentProperties& rData,
831 const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >&
832 rProvider,
833 const rtl::OUString& rContentId )
835 // Note: Empty sequence means "get values of all supported properties".
837 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
838 = new ::ucbhelper::PropertyValueSet( rSMgr );
840 sal_Int32 nCount = rProperties.getLength();
841 if ( nCount )
843 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
844 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
846 const beans::Property* pProps = rProperties.getConstArray();
847 for ( sal_Int32 n = 0; n < nCount; ++n )
849 const beans::Property& rProp = pProps[ n ];
851 // Process Core properties.
853 if ( rProp.Name.equalsAsciiL(
854 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
856 xRow->appendString ( rProp, rData.aContentType );
858 else if ( rProp.Name.equalsAsciiL(
859 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
861 xRow->appendString ( rProp, rData.aTitle );
863 else if ( rProp.Name.equalsAsciiL(
864 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
866 xRow->appendBoolean( rProp, rData.bIsDocument );
868 else if ( rProp.Name.equalsAsciiL(
869 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
871 xRow->appendBoolean( rProp, rData.bIsFolder );
873 else if ( rProp.Name.equalsAsciiL(
874 RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
876 xRow->appendString ( rProp, rData.aMediaType );
878 else if ( rProp.Name.equalsAsciiL(
879 RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
881 // Property only available for streams.
882 if ( rData.bIsDocument )
883 xRow->appendLong( rProp, rData.nSize );
884 else
885 xRow->appendVoid( rProp );
887 else if ( rProp.Name.equalsAsciiL(
888 RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) )
890 // Property only available for streams.
891 if ( rData.bIsDocument )
892 xRow->appendBoolean( rProp, rData.bCompressed );
893 else
894 xRow->appendVoid( rProp );
896 else if ( rProp.Name.equalsAsciiL(
897 RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) )
899 // Property only available for streams.
900 if ( rData.bIsDocument )
901 xRow->appendBoolean( rProp, rData.bEncrypted );
902 else
903 xRow->appendVoid( rProp );
905 else if ( rProp.Name.equalsAsciiL(
906 RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) )
908 // Property only available for root folder.
909 PackageUri aURI( rContentId );
910 if ( aURI.isRootFolder() )
911 xRow->appendBoolean( rProp, rData.bHasEncryptedEntries );
912 else
913 xRow->appendVoid( rProp );
915 else
917 // Not a Core Property! Maybe it's an Additional Core Property?!
919 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
921 xAdditionalPropSet
922 = uno::Reference< beans::XPropertySet >(
923 rProvider->getAdditionalPropertySet( rContentId,
924 sal_False ),
925 uno::UNO_QUERY );
926 bTriedToGetAdditonalPropSet = sal_True;
929 if ( xAdditionalPropSet.is() )
931 if ( !xRow->appendPropertySetValue(
932 xAdditionalPropSet,
933 rProp ) )
935 // Append empty entry.
936 xRow->appendVoid( rProp );
939 else
941 // Append empty entry.
942 xRow->appendVoid( rProp );
947 else
949 // Append all Core Properties.
950 xRow->appendString (
951 beans::Property(
952 rtl::OUString::createFromAscii( "ContentType" ),
954 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
955 beans::PropertyAttribute::BOUND
956 | beans::PropertyAttribute::READONLY ),
957 rData.aContentType );
958 xRow->appendString(
959 beans::Property(
960 rtl::OUString::createFromAscii( "Title" ),
962 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
963 beans::PropertyAttribute::BOUND ),
964 rData.aTitle );
965 xRow->appendBoolean(
966 beans::Property(
967 rtl::OUString::createFromAscii( "IsDocument" ),
969 getCppuBooleanType(),
970 beans::PropertyAttribute::BOUND
971 | beans::PropertyAttribute::READONLY ),
972 rData.bIsDocument );
973 xRow->appendBoolean(
974 beans::Property(
975 rtl::OUString::createFromAscii( "IsFolder" ),
977 getCppuBooleanType(),
978 beans::PropertyAttribute::BOUND
979 | beans::PropertyAttribute::READONLY ),
980 rData.bIsFolder );
981 xRow->appendString(
982 beans::Property(
983 rtl::OUString::createFromAscii( "MediaType" ),
985 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
986 beans::PropertyAttribute::BOUND ),
987 rData.aMediaType );
989 // Properties only available for streams.
990 if ( rData.bIsDocument )
992 xRow->appendLong(
993 beans::Property(
994 rtl::OUString::createFromAscii( "Size" ),
996 getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
997 beans::PropertyAttribute::BOUND
998 | beans::PropertyAttribute::READONLY ),
999 rData.nSize );
1001 xRow->appendBoolean(
1002 beans::Property(
1003 rtl::OUString::createFromAscii( "Compressed" ),
1005 getCppuBooleanType(),
1006 beans::PropertyAttribute::BOUND ),
1007 rData.bCompressed );
1009 xRow->appendBoolean(
1010 beans::Property(
1011 rtl::OUString::createFromAscii( "Encrypted" ),
1013 getCppuBooleanType(),
1014 beans::PropertyAttribute::BOUND ),
1015 rData.bEncrypted );
1018 // Properties only available for root folder.
1019 PackageUri aURI( rContentId );
1020 if ( aURI.isRootFolder() )
1022 xRow->appendBoolean(
1023 beans::Property(
1024 rtl::OUString::createFromAscii( "HasEncryptedEntries" ),
1026 getCppuBooleanType(),
1027 beans::PropertyAttribute::BOUND
1028 | beans::PropertyAttribute::READONLY ),
1029 rData.bHasEncryptedEntries );
1032 // Append all Additional Core Properties.
1034 uno::Reference< beans::XPropertySet > xSet(
1035 rProvider->getAdditionalPropertySet( rContentId, sal_False ),
1036 uno::UNO_QUERY );
1037 xRow->appendPropertySet( xSet );
1040 return uno::Reference< sdbc::XRow >( xRow.get() );
1043 //=========================================================================
1044 uno::Reference< sdbc::XRow > Content::getPropertyValues(
1045 const uno::Sequence< beans::Property >& rProperties )
1047 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1048 return getPropertyValues( m_xSMgr,
1049 rProperties,
1050 m_aProps,
1051 rtl::Reference<
1052 ::ucbhelper::ContentProviderImplHelper >(
1053 m_xProvider.get() ),
1054 m_xIdentifier->getContentIdentifier() );
1057 //=========================================================================
1058 uno::Sequence< uno::Any > Content::setPropertyValues(
1059 const uno::Sequence< beans::PropertyValue >& rValues,
1060 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1061 throw( uno::Exception )
1063 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1065 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1066 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1067 sal_Int32 nChanged = 0;
1069 beans::PropertyChangeEvent aEvent;
1070 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1071 aEvent.Further = sal_False;
1072 // aEvent.PropertyName =
1073 aEvent.PropertyHandle = -1;
1074 // aEvent.OldValue =
1075 // aEvent.NewValue =
1077 const beans::PropertyValue* pValues = rValues.getConstArray();
1078 sal_Int32 nCount = rValues.getLength();
1080 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1081 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1082 sal_Bool bExchange = sal_False;
1083 sal_Bool bStore = sal_False;
1084 rtl::OUString aNewTitle;
1085 sal_Int32 nTitlePos = -1;
1087 for ( sal_Int32 n = 0; n < nCount; ++n )
1089 const beans::PropertyValue& rValue = pValues[ n ];
1091 if ( rValue.Name.equalsAsciiL(
1092 RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
1094 // Read-only property!
1095 aRet[ n ] <<= lang::IllegalAccessException(
1096 rtl::OUString::createFromAscii(
1097 "Property is read-only!" ),
1098 static_cast< cppu::OWeakObject * >( this ) );
1100 else if ( rValue.Name.equalsAsciiL(
1101 RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) )
1103 // Read-only property!
1104 aRet[ n ] <<= lang::IllegalAccessException(
1105 rtl::OUString::createFromAscii(
1106 "Property is read-only!" ),
1107 static_cast< cppu::OWeakObject * >( this ) );
1109 else if ( rValue.Name.equalsAsciiL(
1110 RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) )
1112 // Read-only property!
1113 aRet[ n ] <<= lang::IllegalAccessException(
1114 rtl::OUString::createFromAscii(
1115 "Property is read-only!" ),
1116 static_cast< cppu::OWeakObject * >( this ) );
1118 else if ( rValue.Name.equalsAsciiL(
1119 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1121 if ( m_aUri.isRootFolder() )
1123 // Read-only property!
1124 aRet[ n ] <<= lang::IllegalAccessException(
1125 rtl::OUString::createFromAscii(
1126 "Property is read-only!" ),
1127 static_cast< cppu::OWeakObject * >( this ) );
1129 else
1131 rtl::OUString aNewValue;
1132 if ( rValue.Value >>= aNewValue )
1134 // No empty titles!
1135 if ( aNewValue.getLength() > 0 )
1137 if ( aNewValue != m_aProps.aTitle )
1139 // modified title -> modified URL -> exchange !
1140 if ( m_eState == PERSISTENT )
1141 bExchange = sal_True;
1143 // new value will be set later...
1144 aNewTitle = aNewValue;
1146 // remember position within sequence of values
1147 // (for error handling).
1148 nTitlePos = n;
1151 else
1153 aRet[ n ] <<=
1154 lang::IllegalArgumentException(
1155 rtl::OUString::createFromAscii(
1156 "Empty title not allowed!" ),
1157 static_cast< cppu::OWeakObject * >( this ),
1158 -1 );
1161 else
1163 aRet[ n ] <<=
1164 beans::IllegalTypeException(
1165 rtl::OUString::createFromAscii(
1166 "Property value has wrong type!" ),
1167 static_cast< cppu::OWeakObject * >( this ) );
1171 else if ( rValue.Name.equalsAsciiL(
1172 RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) )
1174 rtl::OUString aNewValue;
1175 if ( rValue.Value >>= aNewValue )
1177 if ( aNewValue != m_aProps.aMediaType )
1179 aEvent.PropertyName = rValue.Name;
1180 aEvent.OldValue = uno::makeAny( m_aProps.aMediaType );
1181 aEvent.NewValue = uno::makeAny( aNewValue );
1183 m_aProps.aMediaType = aNewValue;
1184 nChanged++;
1185 bStore = sal_True;
1186 m_nModifiedProps |= MEDIATYPE_MODIFIED;
1189 else
1191 aRet[ n ] <<= beans::IllegalTypeException(
1192 rtl::OUString::createFromAscii(
1193 "Property value has wrong type!" ),
1194 static_cast< cppu::OWeakObject * >( this ) );
1197 else if ( rValue.Name.equalsAsciiL(
1198 RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
1200 // Read-only property!
1201 aRet[ n ] <<= lang::IllegalAccessException(
1202 rtl::OUString::createFromAscii(
1203 "Property is read-only!" ),
1204 static_cast< cppu::OWeakObject * >( this ) );
1206 else if ( rValue.Name.equalsAsciiL(
1207 RTL_CONSTASCII_STRINGPARAM( "Compressed" ) ) )
1209 // Property only available for streams.
1210 if ( m_aProps.bIsDocument )
1212 sal_Bool bNewValue;
1213 if ( rValue.Value >>= bNewValue )
1215 if ( bNewValue != m_aProps.bCompressed )
1217 aEvent.PropertyName = rValue.Name;
1218 aEvent.OldValue = uno::makeAny( m_aProps.bCompressed );
1219 aEvent.NewValue = uno::makeAny( bNewValue );
1221 m_aProps.bCompressed = bNewValue;
1222 nChanged++;
1223 bStore = sal_True;
1224 m_nModifiedProps |= COMPRESSED_MODIFIED;
1227 else
1229 aRet[ n ] <<= beans::IllegalTypeException(
1230 rtl::OUString::createFromAscii(
1231 "Property value has wrong type!" ),
1232 static_cast< cppu::OWeakObject * >( this ) );
1235 else
1237 aRet[ n ] <<= beans::UnknownPropertyException(
1238 rtl::OUString::createFromAscii(
1239 "Compressed only supported by streams!" ),
1240 static_cast< cppu::OWeakObject * >( this ) );
1243 else if ( rValue.Name.equalsAsciiL(
1244 RTL_CONSTASCII_STRINGPARAM( "Encrypted" ) ) )
1246 // Property only available for streams.
1247 if ( m_aProps.bIsDocument )
1249 sal_Bool bNewValue;
1250 if ( rValue.Value >>= bNewValue )
1252 if ( bNewValue != m_aProps.bEncrypted )
1254 aEvent.PropertyName = rValue.Name;
1255 aEvent.OldValue = uno::makeAny( m_aProps.bEncrypted );
1256 aEvent.NewValue = uno::makeAny( bNewValue );
1258 m_aProps.bEncrypted = bNewValue;
1259 nChanged++;
1260 bStore = sal_True;
1261 m_nModifiedProps |= ENCRYPTED_MODIFIED;
1264 else
1266 aRet[ n ] <<= beans::IllegalTypeException(
1267 rtl::OUString::createFromAscii(
1268 "Property value has wrong type!" ),
1269 static_cast< cppu::OWeakObject * >( this ) );
1272 else
1274 aRet[ n ] <<= beans::UnknownPropertyException(
1275 rtl::OUString::createFromAscii(
1276 "Encrypted only supported by streams!" ),
1277 static_cast< cppu::OWeakObject * >( this ) );
1280 else if ( rValue.Name.equalsAsciiL(
1281 RTL_CONSTASCII_STRINGPARAM( "HasEncryptedEntries" ) ) )
1283 // Read-only property!
1284 aRet[ n ] <<= lang::IllegalAccessException(
1285 rtl::OUString::createFromAscii(
1286 "Property is read-only!" ),
1287 static_cast< cppu::OWeakObject * >( this ) );
1289 else if ( rValue.Name.equalsAsciiL(
1290 RTL_CONSTASCII_STRINGPARAM( "EncryptionKey" ) ) )
1292 // @@@ This is a temporary solution. In the future submitting
1293 // the key should be done using an interaction handler!
1295 // Write-Only property. Only supported by root folder and streams
1296 // (all non-root folders of a package have the same encryption key).
1297 if ( m_aUri.isRootFolder() || m_aProps.bIsDocument )
1299 uno::Sequence < sal_Int8 > aNewValue;
1300 if ( rValue.Value >>= aNewValue )
1302 if ( aNewValue != m_aProps.aEncryptionKey )
1304 aEvent.PropertyName = rValue.Name;
1305 aEvent.OldValue = uno::makeAny(
1306 m_aProps.aEncryptionKey );
1307 aEvent.NewValue = uno::makeAny( aNewValue );
1309 m_aProps.aEncryptionKey = aNewValue;
1310 nChanged++;
1311 bStore = sal_True;
1312 m_nModifiedProps |= ENCRYPTIONKEY_MODIFIED;
1315 else
1317 aRet[ n ] <<= beans::IllegalTypeException(
1318 rtl::OUString::createFromAscii(
1319 "Property value has wrong type!" ),
1320 static_cast< cppu::OWeakObject * >( this ) );
1323 else
1325 aRet[ n ] <<= beans::UnknownPropertyException(
1326 rtl::OUString::createFromAscii(
1327 "EncryptionKey not supported by non-root folder!" ),
1328 static_cast< cppu::OWeakObject * >( this ) );
1331 else
1333 // Not a Core Property! Maybe it's an Additional Core Property?!
1335 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1337 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1338 bTriedToGetAdditonalPropSet = sal_True;
1341 if ( xAdditionalPropSet.is() )
1345 uno::Any aOldValue
1346 = xAdditionalPropSet->getPropertyValue( rValue.Name );
1347 if ( aOldValue != rValue.Value )
1349 xAdditionalPropSet->setPropertyValue(
1350 rValue.Name, rValue.Value );
1352 aEvent.PropertyName = rValue.Name;
1353 aEvent.OldValue = aOldValue;
1354 aEvent.NewValue = rValue.Value;
1356 aChanges.getArray()[ nChanged ] = aEvent;
1357 nChanged++;
1360 catch ( beans::UnknownPropertyException const & e )
1362 aRet[ n ] <<= e;
1364 catch ( lang::WrappedTargetException const & e )
1366 aRet[ n ] <<= e;
1368 catch ( beans::PropertyVetoException const & e )
1370 aRet[ n ] <<= e;
1372 catch ( lang::IllegalArgumentException const & e )
1374 aRet[ n ] <<= e;
1377 else
1379 aRet[ n ] <<= uno::Exception(
1380 rtl::OUString::createFromAscii(
1381 "No property set for storing the value!" ),
1382 static_cast< cppu::OWeakObject * >( this ) );
1387 if ( bExchange )
1389 uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier;
1391 // Assemble new content identifier...
1392 rtl::OUString aNewURL = m_aUri.getParentUri();
1393 aNewURL += rtl::OUString::createFromAscii( "/" );
1394 aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle );
1395 uno::Reference< ucb::XContentIdentifier > xNewId
1396 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL );
1398 aGuard.clear();
1399 if ( exchangeIdentity( xNewId ) )
1401 // Adapt persistent data.
1402 renameData( xOldId, xNewId );
1404 // Adapt Additional Core Properties.
1405 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1406 xNewId->getContentIdentifier(),
1407 sal_True );
1409 else
1411 // Do not set new title!
1412 aNewTitle = rtl::OUString();
1414 // Set error .
1415 aRet[ nTitlePos ] <<= uno::Exception(
1416 rtl::OUString::createFromAscii( "Exchange failed!" ),
1417 static_cast< cppu::OWeakObject * >( this ) );
1421 if ( aNewTitle.getLength() )
1423 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
1424 aEvent.OldValue = uno::makeAny( m_aProps.aTitle );
1425 aEvent.NewValue = uno::makeAny( aNewTitle );
1427 m_aProps.aTitle = aNewTitle;
1429 aChanges.getArray()[ nChanged ] = aEvent;
1430 nChanged++;
1433 if ( nChanged > 0 )
1435 // Save changes, if content was already made persistent.
1436 if ( ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) ||
1437 ( bStore && ( m_eState == PERSISTENT ) ) )
1439 if ( !storeData( uno::Reference< io::XInputStream >() ) )
1441 uno::Any aProps
1442 = uno::makeAny(
1443 beans::PropertyValue(
1444 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1445 "Uri")),
1447 uno::makeAny(m_xIdentifier->
1448 getContentIdentifier()),
1449 beans::PropertyState_DIRECT_VALUE));
1450 ucbhelper::cancelCommandExecution(
1451 ucb::IOErrorCode_CANT_WRITE,
1452 uno::Sequence< uno::Any >(&aProps, 1),
1453 xEnv,
1454 rtl::OUString::createFromAscii(
1455 "Cannot store persistent data!" ),
1456 this );
1457 // Unreachable
1461 aGuard.clear();
1462 aChanges.realloc( nChanged );
1463 notifyPropertiesChange( aChanges );
1466 return aRet;
1469 //=========================================================================
1470 uno::Any Content::open(
1471 const ucb::OpenCommandArgument2& rArg,
1472 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1473 throw( uno::Exception )
1475 if ( rArg.Mode == ucb::OpenMode::ALL ||
1476 rArg.Mode == ucb::OpenMode::FOLDERS ||
1477 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1479 //////////////////////////////////////////////////////////////////
1480 // open command for a folder content
1481 //////////////////////////////////////////////////////////////////
1483 uno::Reference< ucb::XDynamicResultSet > xSet
1484 = new DynamicResultSet( m_xSMgr, this, rArg, xEnv );
1485 return uno::makeAny( xSet );
1487 else
1489 //////////////////////////////////////////////////////////////////
1490 // open command for a document content
1491 //////////////////////////////////////////////////////////////////
1493 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1494 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1496 // Currently(?) unsupported.
1497 ucbhelper::cancelCommandExecution(
1498 uno::makeAny( ucb::UnsupportedOpenModeException(
1499 rtl::OUString(),
1500 static_cast< cppu::OWeakObject * >( this ),
1501 sal_Int16( rArg.Mode ) ) ),
1502 xEnv );
1503 // Unreachable
1506 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
1507 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1508 if ( xOut.is() )
1510 // PUSH: write data into xOut
1512 uno::Reference< io::XInputStream > xIn = getInputStream();
1513 if ( !xIn.is() )
1515 // No interaction if we are not persistent!
1516 uno::Any aProps
1517 = uno::makeAny(
1518 beans::PropertyValue(
1519 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1520 "Uri")),
1522 uno::makeAny(m_xIdentifier->
1523 getContentIdentifier()),
1524 beans::PropertyState_DIRECT_VALUE));
1525 ucbhelper::cancelCommandExecution(
1526 ucb::IOErrorCode_CANT_READ,
1527 uno::Sequence< uno::Any >(&aProps, 1),
1528 m_eState == PERSISTENT
1529 ? xEnv
1530 : uno::Reference< ucb::XCommandEnvironment >(),
1531 rtl::OUString::createFromAscii( "Got no data stream!" ),
1532 this );
1533 // Unreachable
1538 uno::Sequence< sal_Int8 > aBuffer;
1539 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1541 while ( nRead > 0 )
1543 aBuffer.realloc( nRead );
1544 xOut->writeBytes( aBuffer );
1545 aBuffer.realloc( 0 );
1546 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1549 xOut->closeOutput();
1551 catch ( io::NotConnectedException const & )
1553 // closeOutput, readSomeBytes, writeBytes
1555 catch ( io::BufferSizeExceededException const & )
1557 // closeOutput, readSomeBytes, writeBytes
1559 catch ( io::IOException const & )
1561 // closeOutput, readSomeBytes, writeBytes
1564 else
1566 uno::Reference< io::XActiveDataSink > xDataSink(
1567 rArg.Sink, uno::UNO_QUERY );
1568 if ( xDataSink.is() )
1570 // PULL: wait for client read
1572 uno::Reference< io::XInputStream > xIn = getInputStream();
1573 if ( !xIn.is() )
1575 // No interaction if we are not persistent!
1576 uno::Any aProps
1577 = uno::makeAny(
1578 beans::PropertyValue(
1579 rtl::OUString(
1580 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1582 uno::makeAny(m_xIdentifier->
1583 getContentIdentifier()),
1584 beans::PropertyState_DIRECT_VALUE));
1585 ucbhelper::cancelCommandExecution(
1586 ucb::IOErrorCode_CANT_READ,
1587 uno::Sequence< uno::Any >(&aProps, 1),
1588 m_eState == PERSISTENT
1589 ? xEnv
1590 : uno::Reference<
1591 ucb::XCommandEnvironment >(),
1592 rtl::OUString::createFromAscii(
1593 "Got no data stream!" ),
1594 this );
1595 // Unreachable
1598 // Done.
1599 xDataSink->setInputStream( xIn );
1601 else
1603 // Note: aOpenCommand.Sink may contain an XStream
1604 // implementation. Support for this type of
1605 // sink is optional...
1606 ucbhelper::cancelCommandExecution(
1607 uno::makeAny(
1608 ucb::UnsupportedDataSinkException(
1609 rtl::OUString(),
1610 static_cast< cppu::OWeakObject * >( this ),
1611 rArg.Sink ) ),
1612 xEnv );
1613 // Unreachable
1618 return uno::Any();
1621 //=========================================================================
1622 void Content::insert(
1623 const uno::Reference< io::XInputStream >& xStream,
1624 sal_Int32 nNameClashResolve,
1625 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1626 throw( uno::Exception )
1628 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1630 // Check, if all required properties were set.
1631 if ( isFolder() )
1633 // Required: Title
1635 if ( !m_aProps.aTitle.getLength() )
1636 m_aProps.aTitle = m_aUri.getName();
1638 else
1640 // Required: rArg.Data
1642 if ( !xStream.is() )
1644 ucbhelper::cancelCommandExecution(
1645 uno::makeAny( ucb::MissingInputStreamException(
1646 rtl::OUString(),
1647 static_cast< cppu::OWeakObject * >( this ) ) ),
1648 xEnv );
1649 // Unreachable
1652 // Required: Title
1654 if ( !m_aProps.aTitle.getLength() )
1655 m_aProps.aTitle = m_aUri.getName();
1658 rtl::OUString aNewURL = m_aUri.getParentUri();
1659 if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength())
1660 aNewURL += rtl::OUString::createFromAscii( "/" );
1661 aNewURL += ::ucb_impl::urihelper::encodeSegment( m_aProps.aTitle );
1662 PackageUri aNewUri( aNewURL );
1664 // Handle possible name clash...
1665 switch ( nNameClashResolve )
1667 // fail.
1668 case ucb::NameClash::ERROR:
1669 if ( hasData( aNewUri ) )
1671 ucbhelper::cancelCommandExecution(
1672 uno::makeAny( ucb::NameClashException(
1673 rtl::OUString(),
1674 static_cast< cppu::OWeakObject * >( this ),
1675 task::InteractionClassification_ERROR,
1676 m_aProps.aTitle ) ),
1677 xEnv );
1678 // Unreachable
1680 break;
1682 // replace (possibly) existing object.
1683 case ucb::NameClash::OVERWRITE:
1684 break;
1686 // "invent" a new valid title.
1687 case ucb::NameClash::RENAME:
1688 if ( hasData( aNewUri ) )
1690 sal_Int32 nTry = 0;
1694 rtl::OUString aNew = aNewUri.getUri();
1695 aNew += rtl::OUString::createFromAscii( "_" );
1696 aNew += rtl::OUString::valueOf( ++nTry );
1697 aNewUri.setUri( aNew );
1699 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1701 if ( nTry == 1000 )
1703 ucbhelper::cancelCommandExecution(
1704 uno::makeAny(
1705 ucb::UnsupportedNameClashException(
1706 rtl::OUString::createFromAscii(
1707 "Unable to resolve name clash!" ),
1708 static_cast< cppu::OWeakObject * >( this ),
1709 nNameClashResolve ) ),
1710 xEnv );
1711 // Unreachable
1713 else
1715 m_aProps.aTitle += rtl::OUString::createFromAscii( "_" );
1716 m_aProps.aTitle += rtl::OUString::valueOf( nTry );
1719 break;
1721 case ucb::NameClash::KEEP: // deprecated
1722 case ucb::NameClash::ASK:
1723 default:
1724 if ( hasData( aNewUri ) )
1726 ucbhelper::cancelCommandExecution(
1727 uno::makeAny(
1728 ucb::UnsupportedNameClashException(
1729 rtl::OUString(),
1730 static_cast< cppu::OWeakObject * >( this ),
1731 nNameClashResolve ) ),
1732 xEnv );
1733 // Unreachable
1735 break;
1738 // Identifier changed?
1739 sal_Bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() );
1741 if ( bNewId )
1743 m_xIdentifier = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL );
1744 m_aUri = aNewUri;
1747 if ( !storeData( xStream ) )
1749 uno::Any aProps
1750 = uno::makeAny(beans::PropertyValue(
1751 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1752 "Uri")),
1754 uno::makeAny(m_xIdentifier->
1755 getContentIdentifier()),
1756 beans::PropertyState_DIRECT_VALUE));
1757 ucbhelper::cancelCommandExecution(
1758 ucb::IOErrorCode_CANT_WRITE,
1759 uno::Sequence< uno::Any >(&aProps, 1),
1760 xEnv,
1761 rtl::OUString::createFromAscii( "Cannot store persistent data!" ),
1762 this );
1763 // Unreachable
1766 m_eState = PERSISTENT;
1768 if ( bNewId )
1770 // Take over correct default values from underlying packager...
1771 uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess;
1772 loadData( m_pProvider,
1773 m_aUri,
1774 m_aProps,
1775 xXHierarchicalNameAccess );
1777 aGuard.clear();
1778 inserted();
1782 //=========================================================================
1783 void Content::destroy(
1784 sal_Bool bDeletePhysical,
1785 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1786 throw( uno::Exception )
1788 // @@@ take care about bDeletePhysical -> trashcan support
1790 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1792 uno::Reference< ucb::XContent > xThis = this;
1794 // Persistent?
1795 if ( m_eState != PERSISTENT )
1797 ucbhelper::cancelCommandExecution(
1798 uno::makeAny( ucb::UnsupportedCommandException(
1799 rtl::OUString::createFromAscii(
1800 "Not persistent!" ),
1801 static_cast< cppu::OWeakObject * >( this ) ) ),
1802 xEnv );
1803 // Unreachable
1806 m_eState = DEAD;
1808 aGuard.clear();
1809 deleted();
1811 if ( isFolder() )
1813 // Process instanciated children...
1815 ContentRefList aChildren;
1816 queryChildren( aChildren );
1818 ContentRefList::const_iterator it = aChildren.begin();
1819 ContentRefList::const_iterator end = aChildren.end();
1821 while ( it != end )
1823 (*it)->destroy( bDeletePhysical, xEnv );
1824 ++it;
1829 //=========================================================================
1830 void Content::transfer(
1831 const ucb::TransferInfo& rInfo,
1832 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1833 throw( uno::Exception )
1835 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1837 // Persistent?
1838 if ( m_eState != PERSISTENT )
1840 ucbhelper::cancelCommandExecution(
1841 uno::makeAny( ucb::UnsupportedCommandException(
1842 rtl::OUString::createFromAscii(
1843 "Not persistent!" ),
1844 static_cast< cppu::OWeakObject * >( this ) ) ),
1845 xEnv );
1846 // Unreachable
1849 // Is source a package content?
1850 if ( ( rInfo.SourceURL.getLength() == 0 ) ||
1851 ( rInfo.SourceURL.compareTo(
1852 m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) )
1854 ucbhelper::cancelCommandExecution(
1855 uno::makeAny( ucb::InteractiveBadTransferURLException(
1856 rtl::OUString(),
1857 static_cast< cppu::OWeakObject * >( this ) ) ),
1858 xEnv );
1859 // Unreachable
1862 // Is source not a parent of me / not me?
1863 rtl::OUString aId = m_aUri.getParentUri();
1864 aId += rtl::OUString::createFromAscii( "/" );
1866 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1868 if ( aId.compareTo(
1869 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1871 uno::Any aProps
1872 = uno::makeAny(beans::PropertyValue(
1873 rtl::OUString(
1874 RTL_CONSTASCII_USTRINGPARAM("Uri")),
1876 uno::makeAny(rInfo.SourceURL),
1877 beans::PropertyState_DIRECT_VALUE));
1878 ucbhelper::cancelCommandExecution(
1879 ucb::IOErrorCode_RECURSIVE,
1880 uno::Sequence< uno::Any >(&aProps, 1),
1881 xEnv,
1882 rtl::OUString::createFromAscii(
1883 "Target is equal to or is a child of source!" ),
1884 this );
1885 // Unreachable
1889 //////////////////////////////////////////////////////////////////////
1890 // 0) Obtain content object for source.
1891 //////////////////////////////////////////////////////////////////////
1893 uno::Reference< ucb::XContentIdentifier > xId
1894 = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
1896 // Note: The static cast is okay here, because its sure that
1897 // m_xProvider is always the PackageContentProvider.
1898 rtl::Reference< Content > xSource;
1902 xSource = static_cast< Content * >(
1903 m_xProvider->queryContent( xId ).get() );
1905 catch ( ucb::IllegalIdentifierException const & )
1907 // queryContent
1910 if ( !xSource.is() )
1912 uno::Any aProps
1913 = uno::makeAny(beans::PropertyValue(
1914 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1915 "Uri")),
1917 uno::makeAny(xId->getContentIdentifier()),
1918 beans::PropertyState_DIRECT_VALUE));
1919 ucbhelper::cancelCommandExecution(
1920 ucb::IOErrorCode_CANT_READ,
1921 uno::Sequence< uno::Any >(&aProps, 1),
1922 xEnv,
1923 rtl::OUString::createFromAscii(
1924 "Cannot instanciate source object!" ),
1925 this );
1926 // Unreachable
1929 //////////////////////////////////////////////////////////////////////
1930 // 1) Create new child content.
1931 //////////////////////////////////////////////////////////////////////
1933 rtl::OUString aType = xSource->isFolder()
1934 ? GetContentType( m_aUri.getScheme(), sal_True )
1935 : GetContentType( m_aUri.getScheme(), sal_False );
1936 ucb::ContentInfo aContentInfo;
1937 aContentInfo.Type = aType;
1938 aContentInfo.Attributes = 0;
1940 // Note: The static cast is okay here, because its sure that
1941 // createNewContent always creates a Content.
1942 rtl::Reference< Content > xTarget
1943 = static_cast< Content * >( createNewContent( aContentInfo ).get() );
1944 if ( !xTarget.is() )
1946 uno::Any aProps
1947 = uno::makeAny(beans::PropertyValue(
1948 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1949 "Folder")),
1951 uno::makeAny(aId),
1952 beans::PropertyState_DIRECT_VALUE));
1953 ucbhelper::cancelCommandExecution(
1954 ucb::IOErrorCode_CANT_CREATE,
1955 uno::Sequence< uno::Any >(&aProps, 1),
1956 xEnv,
1957 rtl::OUString::createFromAscii(
1958 "XContentCreator::createNewContent failed!" ),
1959 this );
1960 // Unreachable
1963 //////////////////////////////////////////////////////////////////////
1964 // 2) Copy data from source content to child content.
1965 //////////////////////////////////////////////////////////////////////
1967 uno::Sequence< beans::Property > aSourceProps
1968 = xSource->getPropertySetInfo( xEnv )->getProperties();
1969 sal_Int32 nCount = aSourceProps.getLength();
1971 if ( nCount )
1973 sal_Bool bHadTitle = ( rInfo.NewTitle.getLength() == 0 );
1975 // Get all source values.
1976 uno::Reference< sdbc::XRow > xRow
1977 = xSource->getPropertyValues( aSourceProps );
1979 uno::Sequence< beans::PropertyValue > aValues( nCount );
1980 beans::PropertyValue* pValues = aValues.getArray();
1982 const beans::Property* pProps = aSourceProps.getConstArray();
1983 for ( sal_Int32 n = 0; n < nCount; ++n )
1985 const beans::Property& rProp = pProps[ n ];
1986 beans::PropertyValue& rValue = pValues[ n ];
1988 rValue.Name = rProp.Name;
1989 rValue.Handle = rProp.Handle;
1991 if ( !bHadTitle && rProp.Name.equalsAsciiL(
1992 RTL_CONSTASCII_STRINGPARAM( "Title" ) ) )
1994 // Set new title instead of original.
1995 bHadTitle = sal_True;
1996 rValue.Value <<= rInfo.NewTitle;
1998 else
1999 rValue.Value
2000 = xRow->getObject( n + 1,
2001 uno::Reference<
2002 container::XNameAccess >() );
2004 rValue.State = beans::PropertyState_DIRECT_VALUE;
2006 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
2008 // Add Additional Core Property.
2011 xTarget->addProperty( rProp.Name,
2012 rProp.Attributes,
2013 rValue.Value );
2015 catch ( beans::PropertyExistException const & )
2018 catch ( beans::IllegalTypeException const & )
2021 catch ( lang::IllegalArgumentException const & )
2027 // Set target values.
2028 xTarget->setPropertyValues( aValues, xEnv );
2031 //////////////////////////////////////////////////////////////////////
2032 // 3) Commit (insert) child.
2033 //////////////////////////////////////////////////////////////////////
2035 xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv );
2037 //////////////////////////////////////////////////////////////////////
2038 // 4) Transfer (copy) children of source.
2039 //////////////////////////////////////////////////////////////////////
2041 if ( xSource->isFolder() )
2043 uno::Reference< container::XEnumeration > xIter
2044 = xSource->getIterator();
2045 if ( xIter.is() )
2047 while ( xIter->hasMoreElements() )
2051 uno::Reference< container::XNamed > xNamed;
2052 xIter->nextElement() >>= xNamed;
2054 if ( !xNamed.is() )
2056 OSL_ENSURE( sal_False,
2057 "Content::transfer - Got no XNamed!" );
2058 break;
2061 rtl::OUString aName = xNamed->getName();
2063 if ( !aName.getLength() )
2065 OSL_ENSURE( sal_False,
2066 "Content::transfer - Empty name!" );
2067 break;
2070 rtl::OUString aChildId = xId->getContentIdentifier();
2071 if ( ( aChildId.lastIndexOf( '/' ) + 1 )
2072 != aChildId.getLength() )
2073 aChildId += rtl::OUString::createFromAscii( "/" );
2075 aChildId += ::ucb_impl::urihelper::encodeSegment( aName );
2077 ucb::TransferInfo aInfo;
2078 aInfo.MoveData = sal_False;
2079 aInfo.NewTitle = rtl::OUString();
2080 aInfo.SourceURL = aChildId;
2081 aInfo.NameClash = rInfo.NameClash;
2083 // Transfer child to target.
2084 xTarget->transfer( aInfo, xEnv );
2086 catch ( container::NoSuchElementException const & )
2089 catch ( lang::WrappedTargetException const & )
2096 //////////////////////////////////////////////////////////////////////
2097 // 5) Destroy source ( when moving only ) .
2098 //////////////////////////////////////////////////////////////////////
2100 if ( rInfo.MoveData )
2102 xSource->destroy( sal_True, xEnv );
2104 // Remove all persistent data of source and its children.
2105 if ( !xSource->removeData() )
2107 uno::Any aProps
2108 = uno::makeAny(
2109 beans::PropertyValue(
2110 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2111 "Uri")),
2113 uno::makeAny(
2114 xSource->m_xIdentifier->
2115 getContentIdentifier()),
2116 beans::PropertyState_DIRECT_VALUE));
2117 ucbhelper::cancelCommandExecution(
2118 ucb::IOErrorCode_CANT_WRITE,
2119 uno::Sequence< uno::Any >(&aProps, 1),
2120 xEnv,
2121 rtl::OUString::createFromAscii(
2122 "Cannot remove persistent data of source object!" ),
2123 this );
2124 // Unreachable
2127 // Remove own and all children's Additional Core Properties.
2128 xSource->removeAdditionalPropertySet( sal_True );
2132 //=========================================================================
2133 sal_Bool Content::exchangeIdentity(
2134 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2136 if ( !xNewId.is() )
2137 return sal_False;
2139 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
2141 uno::Reference< ucb::XContent > xThis = this;
2143 // Already persistent?
2144 if ( m_eState != PERSISTENT )
2146 OSL_ENSURE( sal_False,
2147 "Content::exchangeIdentity - Not persistent!" );
2148 return sal_False;
2151 // Exchange own identitity.
2153 // Fail, if a content with given id already exists.
2154 PackageUri aNewUri( xNewId->getContentIdentifier() );
2155 if ( !hasData( aNewUri ) )
2157 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
2159 aGuard.clear();
2160 if ( exchange( xNewId ) )
2162 m_aUri = aNewUri;
2163 if ( isFolder() )
2165 // Process instanciated children...
2167 ContentRefList aChildren;
2168 queryChildren( aChildren );
2170 ContentRefList::const_iterator it = aChildren.begin();
2171 ContentRefList::const_iterator end = aChildren.end();
2173 while ( it != end )
2175 ContentRef xChild = (*it);
2177 // Create new content identifier for the child...
2178 uno::Reference< ucb::XContentIdentifier > xOldChildId
2179 = xChild->getIdentifier();
2180 rtl::OUString aOldChildURL
2181 = xOldChildId->getContentIdentifier();
2182 rtl::OUString aNewChildURL
2183 = aOldChildURL.replaceAt(
2185 aOldURL.getLength(),
2186 xNewId->getContentIdentifier() );
2187 uno::Reference< ucb::XContentIdentifier > xNewChildId
2188 = new ::ucbhelper::ContentIdentifier(
2189 m_xSMgr, aNewChildURL );
2191 if ( !xChild->exchangeIdentity( xNewChildId ) )
2192 return sal_False;
2194 ++it;
2197 return sal_True;
2201 OSL_ENSURE( sal_False,
2202 "Content::exchangeIdentity - Panic! Cannot exchange identity!" );
2203 return sal_False;
2206 //=========================================================================
2207 void Content::queryChildren( ContentRefList& rChildren )
2209 // Obtain a list with a snapshot of all currently instanciated contents
2210 // from provider and extract the contents which are direct children
2211 // of this content.
2213 ::ucbhelper::ContentRefList aAllContents;
2214 m_xProvider->queryExistingContents( aAllContents );
2216 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
2218 OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ),
2219 "Content::queryChildren - Invalid URL!" );
2221 aURL += rtl::OUString::createFromAscii( "/" );
2223 sal_Int32 nLen = aURL.getLength();
2225 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
2226 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
2228 while ( it != end )
2230 ::ucbhelper::ContentImplHelperRef xChild = (*it);
2231 rtl::OUString aChildURL
2232 = xChild->getIdentifier()->getContentIdentifier();
2234 // Is aURL a prefix of aChildURL?
2235 if ( ( aChildURL.getLength() > nLen ) &&
2236 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
2238 if ( aChildURL.indexOf( '/', nLen ) == -1 )
2240 // No further slashes. It's a child!
2241 rChildren.push_back(
2242 ContentRef(
2243 static_cast< Content * >( xChild.get() ) ) );
2246 ++it;
2250 //=========================================================================
2251 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage(
2252 const PackageUri& rURI )
2254 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2256 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2257 if ( rURI.getPackage() == m_aUri.getPackage() )
2259 if ( !m_xPackage.is() )
2260 m_xPackage = m_pProvider->createPackage( m_aUri.getPackage(), m_aUri.getParam() );
2262 return m_xPackage;
2265 return m_pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2268 //=========================================================================
2269 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage()
2271 return getPackage( m_aUri );
2274 //=========================================================================
2275 // static
2276 sal_Bool Content::hasData(
2277 ContentProvider* pProvider,
2278 const PackageUri& rURI,
2279 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2281 rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2282 if ( !rxPackage.is() )
2283 return sal_False;
2285 return rxPackage->hasByHierarchicalName( rURI.getPath() );
2288 //=========================================================================
2289 sal_Bool Content::hasData( const PackageUri& rURI )
2291 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2293 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2294 if ( rURI.getPackage() == m_aUri.getPackage() )
2296 xPackage = getPackage();
2297 if ( !xPackage.is() )
2298 return sal_False;
2300 return xPackage->hasByHierarchicalName( rURI.getPath() );
2303 return hasData( m_pProvider, rURI, xPackage );
2306 //=========================================================================
2307 //static
2308 sal_Bool Content::loadData(
2309 ContentProvider* pProvider,
2310 const PackageUri& rURI,
2311 ContentProperties& rProps,
2312 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2314 rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2315 if ( !rxPackage.is() )
2316 return sal_False;
2318 if ( rURI.isRootFolder() )
2320 // Properties available only from package
2321 uno::Reference< beans::XPropertySet > xPackagePropSet(
2322 rxPackage, uno::UNO_QUERY );
2324 OSL_ENSURE( xPackagePropSet.is(),
2325 "Content::loadData - "
2326 "Got no XPropertySet interface from package!" );
2328 if ( xPackagePropSet.is() )
2330 // HasEncryptedEntries ( only avalibale at root folder )
2333 uno::Any aHasEncryptedEntries
2334 = xPackagePropSet->getPropertyValue(
2335 rtl::OUString::createFromAscii(
2336 "HasEncryptedEntries" ) );
2337 if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) )
2339 OSL_ENSURE( sal_False,
2340 "Content::loadData - "
2341 "Got no HasEncryptedEntries value!" );
2342 return sal_False;
2345 catch ( beans::UnknownPropertyException const & )
2347 OSL_ENSURE( sal_False,
2348 "Content::loadData - "
2349 "Got no HasEncryptedEntries value!" );
2350 return sal_False;
2352 catch ( lang::WrappedTargetException const & )
2354 OSL_ENSURE( sal_False,
2355 "Content::loadData - "
2356 "Got no HasEncryptedEntries value!" );
2357 return sal_False;
2362 if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) )
2363 return sal_False;
2367 uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() );
2368 if ( aEntry.hasValue() )
2370 uno::Reference< beans::XPropertySet > xPropSet;
2371 aEntry >>= xPropSet;
2373 if ( !xPropSet.is() )
2375 OSL_ENSURE( sal_False,
2376 "Content::loadData - Got no XPropertySet interface!" );
2377 return sal_False;
2380 // Title
2381 rProps.aTitle = rURI.getName();
2383 // MediaType
2386 uno::Any aMediaType
2387 = xPropSet->getPropertyValue(
2388 rtl::OUString::createFromAscii( "MediaType" ) );
2389 if ( !( aMediaType >>= rProps.aMediaType ) )
2391 OSL_ENSURE( sal_False,
2392 "Content::loadData - Got no MediaType value!" );
2393 return sal_False;
2396 catch ( beans::UnknownPropertyException const & )
2398 OSL_ENSURE( sal_False,
2399 "Content::loadData - Got no MediaType value!" );
2400 return sal_False;
2402 catch ( lang::WrappedTargetException const & )
2404 OSL_ENSURE( sal_False,
2405 "Content::loadData - Got no MediaType value!" );
2406 return sal_False;
2409 uno::Reference< container::XEnumerationAccess > xEnumAccess;
2410 aEntry >>= xEnumAccess;
2412 // ContentType / IsFolder / IsDocument
2413 if ( xEnumAccess.is() )
2415 // folder
2416 rProps.aContentType = GetContentType( rURI.getScheme(), sal_True );
2417 rProps.bIsDocument = sal_False;
2418 rProps.bIsFolder = sal_True;
2420 else
2422 // stream
2423 rProps.aContentType = GetContentType( rURI.getScheme(), sal_False );
2424 rProps.bIsDocument = sal_True;
2425 rProps.bIsFolder = sal_False;
2428 if ( rProps.bIsDocument )
2430 // Size ( only available for streams )
2433 uno::Any aSize
2434 = xPropSet->getPropertyValue(
2435 rtl::OUString::createFromAscii( "Size" ) );
2436 if ( !( aSize >>= rProps.nSize ) )
2438 OSL_ENSURE( sal_False,
2439 "Content::loadData - Got no Size value!" );
2440 return sal_False;
2443 catch ( beans::UnknownPropertyException const & )
2445 OSL_ENSURE( sal_False,
2446 "Content::loadData - Got no Size value!" );
2447 return sal_False;
2449 catch ( lang::WrappedTargetException const & )
2451 OSL_ENSURE( sal_False,
2452 "Content::loadData - Got no Size value!" );
2453 return sal_False;
2456 // Compressed ( only available for streams )
2459 uno::Any aCompressed
2460 = xPropSet->getPropertyValue(
2461 rtl::OUString::createFromAscii( "Compressed" ) );
2462 if ( !( aCompressed >>= rProps.bCompressed ) )
2464 OSL_ENSURE( sal_False,
2465 "Content::loadData - Got no Compressed value!" );
2466 return sal_False;
2469 catch ( beans::UnknownPropertyException const & )
2471 OSL_ENSURE( sal_False,
2472 "Content::loadData - Got no Compressed value!" );
2473 return sal_False;
2475 catch ( lang::WrappedTargetException const & )
2477 OSL_ENSURE( sal_False,
2478 "Content::loadData - Got no Compressed value!" );
2479 return sal_False;
2482 // Encrypted ( only available for streams )
2485 uno::Any aEncrypted
2486 = xPropSet->getPropertyValue(
2487 rtl::OUString::createFromAscii( "Encrypted" ) );
2488 if ( !( aEncrypted >>= rProps.bEncrypted ) )
2490 OSL_ENSURE( sal_False,
2491 "Content::loadData - Got no Encrypted value!" );
2492 return sal_False;
2495 catch ( beans::UnknownPropertyException const & )
2497 OSL_ENSURE( sal_False,
2498 "Content::loadData - Got no Encrypted value!" );
2499 return sal_False;
2501 catch ( lang::WrappedTargetException const & )
2503 OSL_ENSURE( sal_False,
2504 "Content::loadData - Got no Encrypted value!" );
2505 return sal_False;
2508 return sal_True;
2511 catch ( container::NoSuchElementException const & )
2513 // getByHierarchicalName
2516 return sal_False;
2519 //=========================================================================
2520 sal_Bool Content::renameData(
2521 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2522 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2524 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2526 PackageUri aURI( xOldId->getContentIdentifier() );
2527 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(
2528 aURI );
2529 if ( !xNA.is() )
2530 return sal_False;
2532 if ( !xNA->hasByHierarchicalName( aURI.getPath() ) )
2533 return sal_False;
2537 uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() );
2538 uno::Reference< container::XNamed > xNamed;
2539 aEntry >>= xNamed;
2541 if ( !xNamed.is() )
2543 OSL_ENSURE( sal_False,
2544 "Content::renameData - Got no XNamed interface!" );
2545 return sal_False;
2548 PackageUri aNewURI( xNewId->getContentIdentifier() );
2550 // No success indicator!? No return value / exceptions specified.
2551 xNamed->setName( aNewURI.getName() );
2553 return sal_True;
2555 catch ( container::NoSuchElementException const & )
2557 // getByHierarchicalName
2560 return sal_False;
2563 //=========================================================================
2564 sal_Bool Content::storeData( const uno::Reference< io::XInputStream >& xStream )
2566 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2568 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2569 if ( !xNA.is() )
2570 return sal_False;
2572 uno::Reference< beans::XPropertySet > xPackagePropSet(
2573 xNA, uno::UNO_QUERY );
2574 OSL_ENSURE( xPackagePropSet.is(),
2575 "Content::storeData - "
2576 "Got no XPropertySet interface from package!" );
2578 if ( !xPackagePropSet.is() )
2579 return sal_False;
2581 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2583 if ( m_aUri.isRootFolder() )
2585 // Property available only from package and from streams (see below)
2588 xPackagePropSet->setPropertyValue(
2589 rtl::OUString::createFromAscii( "EncryptionKey" ),
2590 uno::makeAny( m_aProps.aEncryptionKey ) );
2591 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2593 catch ( beans::UnknownPropertyException const & )
2595 // setPropertyValue
2597 catch ( beans::PropertyVetoException const & )
2599 // setPropertyValue
2601 catch ( lang::IllegalArgumentException const & )
2603 // setPropertyValue
2605 catch ( lang::WrappedTargetException const & )
2607 // setPropertyValue
2612 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2614 // if ( !bCreate )
2615 // return sal_True;
2619 // Create new resource...
2620 uno::Reference< lang::XSingleServiceFactory > xFac(
2621 xNA, uno::UNO_QUERY );
2622 if ( !xFac.is() )
2624 OSL_ENSURE( sal_False,
2625 "Content::storeData - "
2626 "Got no XSingleServiceFactory interface!" );
2627 return sal_False;
2630 uno::Sequence< uno::Any > aArgs( 1 );
2631 aArgs[ 0 ] <<= isFolder();
2633 uno::Reference< uno::XInterface > xNew
2634 = xFac->createInstanceWithArguments( aArgs );
2636 if ( !xNew.is() )
2638 OSL_ENSURE( sal_False,
2639 "Content::storeData - createInstance failed!" );
2640 return sal_False;
2643 PackageUri aParentUri( getParentURL() );
2644 uno::Any aEntry
2645 = xNA->getByHierarchicalName( aParentUri.getPath() );
2646 uno::Reference< container::XNameContainer > xParentContainer;
2647 aEntry >>= xParentContainer;
2649 if ( !xParentContainer.is() )
2651 OSL_ENSURE( sal_False,
2652 "Content::storeData - "
2653 "Got no XNameContainer interface!" );
2654 return sal_False;
2657 xParentContainer->insertByName( m_aProps.aTitle,
2658 uno::makeAny( xNew ) );
2660 catch ( uno::RuntimeException const & )
2662 throw;
2664 catch ( lang::IllegalArgumentException const & )
2666 // insertByName
2667 OSL_ENSURE( sal_False,
2668 "Content::storeData - insertByName failed!" );
2669 return sal_False;
2671 catch ( container::ElementExistException const & )
2673 // insertByName
2674 OSL_ENSURE( sal_False,
2675 "Content::storeData - insertByName failed!" );
2676 return sal_False;
2678 catch ( lang::WrappedTargetException const & )
2680 // insertByName
2681 OSL_ENSURE( sal_False,
2682 "Content::storeData - insertByName failed!" );
2683 return sal_False;
2685 catch ( container::NoSuchElementException const & )
2687 // getByHierarchicalName
2688 OSL_ENSURE( sal_False,
2689 "Content::storeData - getByHierarchicalName failed!" );
2690 return sal_False;
2692 catch ( uno::Exception const & )
2694 // createInstanceWithArguments
2695 OSL_ENSURE( sal_False, "Content::storeData - Error!" );
2696 return sal_False;
2700 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2701 return sal_False;
2705 uno::Reference< beans::XPropertySet > xPropSet;
2706 xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet;
2708 if ( !xPropSet.is() )
2710 OSL_ENSURE( sal_False,
2711 "Content::storeData - Got no XPropertySet interface!" );
2712 return sal_False;
2715 //////////////////////////////////////////////////////////////////
2716 // Store property values...
2717 //////////////////////////////////////////////////////////////////
2719 if ( m_nModifiedProps & MEDIATYPE_MODIFIED )
2721 xPropSet->setPropertyValue(
2722 rtl::OUString::createFromAscii( "MediaType" ),
2723 uno::makeAny( m_aProps.aMediaType ) );
2724 m_nModifiedProps &= ~MEDIATYPE_MODIFIED;
2727 if ( m_nModifiedProps & COMPRESSED_MODIFIED )
2729 if ( !isFolder() )
2730 xPropSet->setPropertyValue(
2731 rtl::OUString::createFromAscii( "Compressed" ),
2732 uno::makeAny( m_aProps.bCompressed ) );
2734 m_nModifiedProps &= ~COMPRESSED_MODIFIED;
2737 if ( m_nModifiedProps & ENCRYPTED_MODIFIED )
2739 if ( !isFolder() )
2740 xPropSet->setPropertyValue(
2741 rtl::OUString::createFromAscii( "Encrypted" ),
2742 uno::makeAny( m_aProps.bEncrypted ) );
2744 m_nModifiedProps &= ~ENCRYPTED_MODIFIED;
2747 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2749 if ( !isFolder() )
2750 xPropSet->setPropertyValue(
2751 rtl::OUString::createFromAscii( "EncryptionKey" ),
2752 uno::makeAny( m_aProps.aEncryptionKey ) );
2754 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2757 //////////////////////////////////////////////////////////////////
2758 // Store data stream...
2759 //////////////////////////////////////////////////////////////////
2761 if ( xStream.is() && !isFolder() )
2763 uno::Reference< io::XActiveDataSink > xSink(
2764 xPropSet, uno::UNO_QUERY );
2766 if ( !xSink.is() )
2768 OSL_ENSURE( sal_False,
2769 "Content::storeData - "
2770 "Got no XActiveDataSink interface!" );
2771 return sal_False;
2774 xSink->setInputStream( xStream );
2777 return sal_True;
2779 catch ( container::NoSuchElementException const & )
2781 // getByHierarchicalName
2783 catch ( beans::UnknownPropertyException const & )
2785 // setPropertyValue
2787 catch ( beans::PropertyVetoException const & )
2789 // setPropertyValue
2791 catch ( lang::IllegalArgumentException const & )
2793 // setPropertyValue
2795 catch ( lang::WrappedTargetException const & )
2797 // setPropertyValue
2800 OSL_ENSURE( sal_False, "Content::storeData - Error!" );
2801 return sal_False;
2804 //=========================================================================
2805 sal_Bool Content::removeData()
2807 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2809 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2810 if ( !xNA.is() )
2811 return sal_False;
2813 PackageUri aParentUri( getParentURL() );
2814 if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) )
2815 return sal_False;
2819 uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() );
2820 uno::Reference< container::XNameContainer > xContainer;
2821 aEntry >>= xContainer;
2823 if ( !xContainer.is() )
2825 OSL_ENSURE( sal_False,
2826 "Content::removeData - "
2827 "Got no XNameContainer interface!" );
2828 return sal_False;
2831 xContainer->removeByName( m_aUri.getName() );
2832 return sal_True;
2834 catch ( container::NoSuchElementException const & )
2836 // getByHierarchicalName, removeByName
2838 catch ( lang::WrappedTargetException const & )
2840 // removeByName
2843 OSL_ENSURE( sal_False, "Content::removeData - Error!" );
2844 return sal_False;
2847 //=========================================================================
2848 sal_Bool Content::flushData()
2850 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2852 // Note: XChangesBatch is only implemented by the package itself, not
2853 // by the single entries. Maybe this has to change...
2855 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2856 if ( !xNA.is() )
2857 return sal_False;
2859 uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY );
2860 if ( !xBatch.is() )
2862 OSL_ENSURE( sal_False,
2863 "Content::flushData - Got no XChangesBatch interface!" );
2864 return sal_False;
2869 xBatch->commitChanges();
2870 return sal_True;
2872 catch ( lang::WrappedTargetException const & )
2876 OSL_ENSURE( sal_False, "Content::flushData - Error!" );
2877 return sal_False;
2880 //=========================================================================
2881 uno::Reference< io::XInputStream > Content::getInputStream()
2883 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2885 uno::Reference< io::XInputStream > xStream;
2886 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2887 if ( !xNA.is() )
2888 return xStream;
2890 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2891 return xStream;
2895 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2896 uno::Reference< io::XActiveDataSink > xSink;
2897 aEntry >>= xSink;
2899 if ( !xSink.is() )
2901 OSL_ENSURE( sal_False,
2902 "Content::getInputStream - "
2903 "Got no XActiveDataSink interface!" );
2904 return xStream;
2907 xStream = xSink->getInputStream();
2909 OSL_ENSURE( xStream.is(),
2910 "Content::getInputStream - Got no stream!" );
2912 catch ( container::NoSuchElementException const & )
2914 // getByHierarchicalName
2917 return xStream;
2920 //=========================================================================
2921 uno::Reference< container::XEnumeration > Content::getIterator()
2923 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2925 uno::Reference< container::XEnumeration > xIter;
2926 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2927 if ( !xNA.is() )
2928 return xIter;
2930 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2931 return xIter;
2935 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2936 uno::Reference< container::XEnumerationAccess > xIterFac;
2937 aEntry >>= xIterFac;
2939 if ( !xIterFac.is() )
2941 OSL_ENSURE( sal_False,
2942 "Content::getIterator - "
2943 "Got no XEnumerationAccess interface!" );
2944 return xIter;
2947 xIter = xIterFac->createEnumeration();
2949 OSL_ENSURE( xIter.is(),
2950 "Content::getIterator - Got no iterator!" );
2952 catch ( container::NoSuchElementException const & )
2954 // getByHierarchicalName
2957 return xIter;