Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / package / pkgcontent.cxx
blob3b4ee22660de62286c4b45ba6ee6466346bfbe20
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 /**************************************************************************
31 TODO
32 **************************************************************************
33 *************************************************************************/
34 #include <osl/diagnose.h>
36 #include "osl/doublecheckedlocking.h"
37 #include <rtl/ustring.h>
38 #include <rtl/ustring.hxx>
39 #include <com/sun/star/beans/PropertyAttribute.hpp>
40 #include <com/sun/star/beans/PropertyState.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/beans/XPropertyAccess.hpp>
43 #include <com/sun/star/container/XEnumerationAccess.hpp>
44 #include <com/sun/star/container/XHierarchicalNameAccess.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 #include <com/sun/star/container/XNamed.hpp>
47 #include <com/sun/star/io/XActiveDataSink.hpp>
48 #include <com/sun/star/io/XInputStream.hpp>
49 #include <com/sun/star/io/XOutputStream.hpp>
50 #include <com/sun/star/lang/IllegalAccessException.hpp>
51 #include <com/sun/star/sdbc/XRow.hpp>
52 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
53 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
54 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
55 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
56 #include <com/sun/star/ucb/NameClash.hpp>
57 #include <com/sun/star/ucb/NameClashException.hpp>
58 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
59 #include <com/sun/star/ucb/OpenMode.hpp>
60 #include <com/sun/star/ucb/TransferInfo.hpp>
61 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
62 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
63 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
64 #include <com/sun/star/ucb/XCommandInfo.hpp>
65 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
66 #include <com/sun/star/util/XChangesBatch.hpp>
67 #include <com/sun/star/uno/Any.hxx>
68 #include <com/sun/star/uno/Sequence.hxx>
69 #include <ucbhelper/contentidentifier.hxx>
70 #include <ucbhelper/propertyvalueset.hxx>
71 #include <ucbhelper/cancelcommandexecution.hxx>
72 #include "pkgcontent.hxx"
73 #include "pkgprovider.hxx"
74 #include "pkgresultset.hxx"
76 #include "../inc/urihelper.hxx"
78 using namespace com::sun::star;
79 using namespace package_ucp;
81 #define NONE_MODIFIED sal_uInt32( 0x00 )
82 #define MEDIATYPE_MODIFIED sal_uInt32( 0x01 )
83 #define COMPRESSED_MODIFIED sal_uInt32( 0x02 )
84 #define ENCRYPTED_MODIFIED sal_uInt32( 0x04 )
85 #define ENCRYPTIONKEY_MODIFIED sal_uInt32( 0x08 )
87 //=========================================================================
88 //=========================================================================
90 // ContentProperties Implementation.
92 //=========================================================================
93 //=========================================================================
95 ContentProperties::ContentProperties( const rtl::OUString& rContentType )
96 : aContentType( rContentType ),
97 nSize( 0 ),
98 bCompressed( sal_True ),
99 bEncrypted( sal_False ),
100 bHasEncryptedEntries( sal_False )
102 bIsFolder = rContentType == PACKAGE_FOLDER_CONTENT_TYPE || rContentType == PACKAGE_ZIP_FOLDER_CONTENT_TYPE;
103 bIsDocument = !bIsFolder;
105 OSL_ENSURE( bIsFolder || rContentType == PACKAGE_STREAM_CONTENT_TYPE || rContentType == PACKAGE_ZIP_STREAM_CONTENT_TYPE,
106 "ContentProperties::ContentProperties - Unknown type!" );
109 //=========================================================================
111 uno::Sequence< ucb::ContentInfo >
112 ContentProperties::getCreatableContentsInfo( PackageUri const & rUri ) const
114 if ( bIsFolder )
116 uno::Sequence< beans::Property > aProps( 1 );
117 aProps.getArray()[ 0 ] = beans::Property(
118 rtl::OUString("Title"),
120 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
121 beans::PropertyAttribute::BOUND );
123 uno::Sequence< ucb::ContentInfo > aSeq( 2 );
125 // Folder.
126 aSeq.getArray()[ 0 ].Type
127 = Content::getContentType( rUri.getScheme(), sal_True );
128 aSeq.getArray()[ 0 ].Attributes
129 = ucb::ContentInfoAttribute::KIND_FOLDER;
130 aSeq.getArray()[ 0 ].Properties = aProps;
132 // Stream.
133 aSeq.getArray()[ 1 ].Type
134 = Content::getContentType( rUri.getScheme(), sal_False );
135 aSeq.getArray()[ 1 ].Attributes
136 = ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
137 | ucb::ContentInfoAttribute::KIND_DOCUMENT;
138 aSeq.getArray()[ 1 ].Properties = aProps;
140 return aSeq;
142 else
144 return uno::Sequence< ucb::ContentInfo >( 0 );
148 //=========================================================================
149 //=========================================================================
151 // Content Implementation.
153 //=========================================================================
154 //=========================================================================
156 // static ( "virtual" ctor )
157 Content* Content::create(
158 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
159 ContentProvider* pProvider,
160 const uno::Reference< ucb::XContentIdentifier >& Identifier )
162 rtl::OUString aURL = Identifier->getContentIdentifier();
163 PackageUri aURI( aURL );
164 ContentProperties aProps;
165 uno::Reference< container::XHierarchicalNameAccess > xPackage;
167 if ( loadData( pProvider, aURI, aProps, xPackage ) )
169 // resource exists
171 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
172 if ( ( nLastSlash + 1 ) == aURL.getLength() )
174 // Client explicitly requested a folder!
175 if ( !aProps.bIsFolder )
176 return 0;
179 uno::Reference< ucb::XContentIdentifier > xId
180 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
181 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aProps );
183 else
185 // resource doesn't exist
187 sal_Bool bFolder = sal_False;
189 // Guess type according to URI.
190 sal_Int32 nLastSlash = aURL.lastIndexOf( '/' );
191 if ( ( nLastSlash + 1 ) == aURL.getLength() )
192 bFolder = sal_True;
194 uno::Reference< ucb::XContentIdentifier > xId
195 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
197 ucb::ContentInfo aInfo;
198 if ( bFolder || aURI.isRootFolder() )
199 aInfo.Type = getContentType( aURI.getScheme(), sal_True );
200 else
201 aInfo.Type = getContentType( aURI.getScheme(), sal_False );
203 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, aInfo );
207 //=========================================================================
208 // static ( "virtual" ctor )
209 Content* Content::create(
210 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
211 ContentProvider* pProvider,
212 const uno::Reference< ucb::XContentIdentifier >& Identifier,
213 const ucb::ContentInfo& Info )
215 if ( Info.Type.isEmpty() )
216 return 0;
218 PackageUri aURI( Identifier->getContentIdentifier() );
220 if ( !Info.Type.equalsIgnoreAsciiCase(
221 getContentType( aURI.getScheme(), sal_True ) ) &&
222 !Info.Type.equalsIgnoreAsciiCase(
223 getContentType( aURI.getScheme(), sal_False ) ) )
224 return 0;
226 uno::Reference< container::XHierarchicalNameAccess > xPackage;
228 xPackage = pProvider->createPackage( aURI.getPackage(), aURI.getParam() );
230 uno::Reference< ucb::XContentIdentifier > xId
231 = new ::ucbhelper::ContentIdentifier( rxSMgr, aURI.getUri() );
232 return new Content( rxSMgr, pProvider, xId, xPackage, aURI, Info );
235 //=========================================================================
236 // static
237 ::rtl::OUString Content::getContentType(
238 const ::rtl::OUString& aScheme, sal_Bool bFolder )
240 return ( rtl::OUString("application/")
241 + aScheme
242 + ( bFolder
243 ? rtl::OUString("-folder")
244 : rtl::OUString("-stream") ) );
247 //=========================================================================
248 Content::Content(
249 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
250 ContentProvider* pProvider,
251 const uno::Reference< ucb::XContentIdentifier >& Identifier,
252 const uno::Reference< container::XHierarchicalNameAccess > & Package,
253 const PackageUri& rUri,
254 const ContentProperties& rProps )
255 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
256 m_aUri( rUri ),
257 m_aProps( rProps ),
258 m_eState( PERSISTENT ),
259 m_xPackage( Package ),
260 m_pProvider( pProvider ),
261 m_nModifiedProps( NONE_MODIFIED )
265 //=========================================================================
266 Content::Content(
267 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
268 ContentProvider* pProvider,
269 const uno::Reference< ucb::XContentIdentifier >& Identifier,
270 const uno::Reference< container::XHierarchicalNameAccess > & Package,
271 const PackageUri& rUri,
272 const ucb::ContentInfo& Info )
273 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
274 m_aUri( rUri ),
275 m_aProps( Info.Type ),
276 m_eState( TRANSIENT ),
277 m_xPackage( Package ),
278 m_pProvider( pProvider ),
279 m_nModifiedProps( NONE_MODIFIED )
283 //=========================================================================
284 // virtual
285 Content::~Content()
289 //=========================================================================
291 // XInterface methods.
293 //=========================================================================
295 // virtual
296 void SAL_CALL Content::acquire()
297 throw( )
299 ContentImplHelper::acquire();
302 //=========================================================================
303 // virtual
304 void SAL_CALL Content::release()
305 throw( )
307 ContentImplHelper::release();
310 //=========================================================================
311 // virtual
312 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
313 throw ( uno::RuntimeException )
315 uno::Any aRet;
317 if ( isFolder() )
318 aRet = cppu::queryInterface(
319 rType, static_cast< ucb::XContentCreator * >( this ) );
321 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
324 //=========================================================================
326 // XTypeProvider methods.
328 //=========================================================================
330 XTYPEPROVIDER_COMMON_IMPL( Content );
332 //=========================================================================
333 // virtual
334 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
335 throw( uno::RuntimeException )
337 cppu::OTypeCollection * pCollection = 0;
339 if ( isFolder() )
341 static cppu::OTypeCollection* pFolderTypes = 0;
343 pCollection = pFolderTypes;
344 if ( !pCollection )
346 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
348 pCollection = pFolderTypes;
349 if ( !pCollection )
351 static cppu::OTypeCollection aCollection(
352 CPPU_TYPE_REF( lang::XTypeProvider ),
353 CPPU_TYPE_REF( lang::XServiceInfo ),
354 CPPU_TYPE_REF( lang::XComponent ),
355 CPPU_TYPE_REF( ucb::XContent ),
356 CPPU_TYPE_REF( ucb::XCommandProcessor ),
357 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
358 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
359 CPPU_TYPE_REF( beans::XPropertyContainer ),
360 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
361 CPPU_TYPE_REF( container::XChild ),
362 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
363 pCollection = &aCollection;
364 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
365 pFolderTypes = pCollection;
368 else {
369 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
372 else
374 static cppu::OTypeCollection* pDocumentTypes = 0;
376 pCollection = pDocumentTypes;
377 if ( !pCollection )
379 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
381 pCollection = pDocumentTypes;
382 if ( !pCollection )
384 static cppu::OTypeCollection aCollection(
385 CPPU_TYPE_REF( lang::XTypeProvider ),
386 CPPU_TYPE_REF( lang::XServiceInfo ),
387 CPPU_TYPE_REF( lang::XComponent ),
388 CPPU_TYPE_REF( ucb::XContent ),
389 CPPU_TYPE_REF( ucb::XCommandProcessor ),
390 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
391 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
392 CPPU_TYPE_REF( beans::XPropertyContainer ),
393 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
394 CPPU_TYPE_REF( container::XChild ) );
395 pCollection = &aCollection;
396 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
397 pDocumentTypes = pCollection;
400 else {
401 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
405 return (*pCollection).getTypes();
408 //=========================================================================
410 // XServiceInfo methods.
412 //=========================================================================
414 // virtual
415 rtl::OUString SAL_CALL Content::getImplementationName()
416 throw( uno::RuntimeException )
418 return rtl::OUString( "com.sun.star.comp.ucb.PackageContent" );
421 //=========================================================================
422 // virtual
423 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
424 throw( uno::RuntimeException )
426 uno::Sequence< rtl::OUString > aSNS( 1 );
427 if ( isFolder() )
428 aSNS.getArray()[ 0 ] = rtl::OUString( PACKAGE_FOLDER_CONTENT_SERVICE_NAME );
429 else
430 aSNS.getArray()[ 0 ] = rtl::OUString( PACKAGE_STREAM_CONTENT_SERVICE_NAME );
432 return aSNS;
435 //=========================================================================
437 // XContent methods.
439 //=========================================================================
441 // virtual
442 rtl::OUString SAL_CALL Content::getContentType()
443 throw( uno::RuntimeException )
445 return m_aProps.aContentType;
448 //=========================================================================
450 // XCommandProcessor methods.
452 //=========================================================================
454 // virtual
455 uno::Any SAL_CALL Content::execute(
456 const ucb::Command& aCommand,
457 sal_Int32 /*CommandId*/,
458 const uno::Reference< ucb::XCommandEnvironment >& Environment )
459 throw( uno::Exception,
460 ucb::CommandAbortedException,
461 uno::RuntimeException )
463 uno::Any aRet;
465 if ( aCommand.Name == "getPropertyValues" )
467 //////////////////////////////////////////////////////////////////
468 // getPropertyValues
469 //////////////////////////////////////////////////////////////////
471 uno::Sequence< beans::Property > Properties;
472 if ( !( aCommand.Argument >>= Properties ) )
474 ucbhelper::cancelCommandExecution(
475 uno::makeAny( lang::IllegalArgumentException(
476 rtl::OUString( "Wrong argument type!" ),
477 static_cast< cppu::OWeakObject * >( this ),
478 -1 ) ),
479 Environment );
480 // Unreachable
483 aRet <<= getPropertyValues( Properties );
485 else if ( aCommand.Name == "setPropertyValues" )
487 //////////////////////////////////////////////////////////////////
488 // setPropertyValues
489 //////////////////////////////////////////////////////////////////
491 uno::Sequence< beans::PropertyValue > aProperties;
492 if ( !( aCommand.Argument >>= aProperties ) )
494 ucbhelper::cancelCommandExecution(
495 uno::makeAny( lang::IllegalArgumentException(
496 rtl::OUString( "Wrong argument type!" ),
497 static_cast< cppu::OWeakObject * >( this ),
498 -1 ) ),
499 Environment );
500 // Unreachable
503 if ( !aProperties.getLength() )
505 ucbhelper::cancelCommandExecution(
506 uno::makeAny( lang::IllegalArgumentException(
507 rtl::OUString( "No properties!" ),
508 static_cast< cppu::OWeakObject * >( this ),
509 -1 ) ),
510 Environment );
511 // Unreachable
514 aRet <<= setPropertyValues( aProperties, Environment );
516 else if ( aCommand.Name == "getPropertySetInfo" )
518 //////////////////////////////////////////////////////////////////
519 // getPropertySetInfo
520 //////////////////////////////////////////////////////////////////
522 // Note: Implemented by base class.
523 aRet <<= getPropertySetInfo( Environment );
525 else if ( aCommand.Name == "getCommandInfo" )
527 //////////////////////////////////////////////////////////////////
528 // getCommandInfo
529 //////////////////////////////////////////////////////////////////
531 // Note: Implemented by base class.
532 aRet <<= getCommandInfo( Environment );
534 else if ( aCommand.Name == "open" )
536 //////////////////////////////////////////////////////////////////
537 // open
538 //////////////////////////////////////////////////////////////////
540 ucb::OpenCommandArgument2 aOpenCommand;
541 if ( !( aCommand.Argument >>= aOpenCommand ) )
543 ucbhelper::cancelCommandExecution(
544 uno::makeAny( lang::IllegalArgumentException(
545 rtl::OUString( "Wrong argument type!" ),
546 static_cast< cppu::OWeakObject * >( this ),
547 -1 ) ),
548 Environment );
549 // Unreachable
552 aRet = open( aOpenCommand, Environment );
554 else if ( !m_aUri.isRootFolder() && aCommand.Name == "insert" )
556 //////////////////////////////////////////////////////////////////
557 // insert
558 //////////////////////////////////////////////////////////////////
560 ucb::InsertCommandArgument aArg;
561 if ( !( aCommand.Argument >>= aArg ) )
563 ucbhelper::cancelCommandExecution(
564 uno::makeAny( lang::IllegalArgumentException(
565 rtl::OUString( "Wrong argument type!" ),
566 static_cast< cppu::OWeakObject * >( this ),
567 -1 ) ),
568 Environment );
569 // Unreachable
572 sal_Int32 nNameClash = aArg.ReplaceExisting
573 ? ucb::NameClash::OVERWRITE
574 : ucb::NameClash::ERROR;
575 insert( aArg.Data, nNameClash, Environment );
577 else if ( !m_aUri.isRootFolder() && aCommand.Name == "delete" )
579 //////////////////////////////////////////////////////////////////
580 // delete
581 //////////////////////////////////////////////////////////////////
583 sal_Bool bDeletePhysical = sal_False;
584 aCommand.Argument >>= bDeletePhysical;
585 destroy( bDeletePhysical, Environment );
587 // Remove own and all children's persistent data.
588 if ( !removeData() )
590 uno::Any aProps
591 = uno::makeAny(
592 beans::PropertyValue(
593 rtl::OUString( "Uri"),
595 uno::makeAny(m_xIdentifier->
596 getContentIdentifier()),
597 beans::PropertyState_DIRECT_VALUE));
598 ucbhelper::cancelCommandExecution(
599 ucb::IOErrorCode_CANT_WRITE,
600 uno::Sequence< uno::Any >(&aProps, 1),
601 Environment,
602 rtl::OUString( "Cannot remove persistent data!" ),
603 this );
604 // Unreachable
607 // Remove own and all children's Additional Core Properties.
608 removeAdditionalPropertySet( sal_True );
610 else if ( aCommand.Name == "transfer" )
612 //////////////////////////////////////////////////////////////////
613 // transfer
614 // ( Not available at stream objects )
615 //////////////////////////////////////////////////////////////////
617 ucb::TransferInfo aInfo;
618 if ( !( aCommand.Argument >>= aInfo ) )
620 ucbhelper::cancelCommandExecution(
621 uno::makeAny( lang::IllegalArgumentException(
622 rtl::OUString( "Wrong argument type!" ),
623 static_cast< cppu::OWeakObject * >( this ),
624 -1 ) ),
625 Environment );
626 // Unreachable
629 transfer( aInfo, Environment );
631 else if ( aCommand.Name == "createNewContent" && isFolder() )
633 //////////////////////////////////////////////////////////////////
634 // createNewContent
635 // ( Not available at stream objects )
636 //////////////////////////////////////////////////////////////////
638 ucb::ContentInfo aInfo;
639 if ( !( aCommand.Argument >>= aInfo ) )
641 OSL_FAIL( "Wrong argument type!" );
642 ucbhelper::cancelCommandExecution(
643 uno::makeAny( lang::IllegalArgumentException(
644 rtl::OUString( "Wrong argument type!" ),
645 static_cast< cppu::OWeakObject * >( this ),
646 -1 ) ),
647 Environment );
648 // Unreachable
651 aRet <<= createNewContent( aInfo );
653 else if ( aCommand.Name == "flush" )
655 //////////////////////////////////////////////////////////////////
656 // flush
657 // ( Not available at stream objects )
658 //////////////////////////////////////////////////////////////////
660 if( !flushData() )
662 uno::Any aProps
663 = uno::makeAny(
664 beans::PropertyValue(
665 rtl::OUString( "Uri"),
667 uno::makeAny(m_xIdentifier->
668 getContentIdentifier()),
669 beans::PropertyState_DIRECT_VALUE));
670 ucbhelper::cancelCommandExecution(
671 ucb::IOErrorCode_CANT_WRITE,
672 uno::Sequence< uno::Any >(&aProps, 1),
673 Environment,
674 rtl::OUString( "Cannot write file to disk!" ),
675 this );
676 // Unreachable
679 else
681 //////////////////////////////////////////////////////////////////
682 // Unsupported command
683 //////////////////////////////////////////////////////////////////
685 ucbhelper::cancelCommandExecution(
686 uno::makeAny( ucb::UnsupportedCommandException(
687 rtl::OUString(),
688 static_cast< cppu::OWeakObject * >( this ) ) ),
689 Environment );
690 // Unreachable
693 return aRet;
696 //=========================================================================
697 // virtual
698 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
699 throw( uno::RuntimeException )
701 // @@@ Implement logic to abort running commands, if this makes
702 // sense for your content.
705 //=========================================================================
707 // XContentCreator methods.
709 //=========================================================================
711 // virtual
712 uno::Sequence< ucb::ContentInfo > SAL_CALL
713 Content::queryCreatableContentsInfo()
714 throw( uno::RuntimeException )
716 return m_aProps.getCreatableContentsInfo( m_aUri );
719 //=========================================================================
720 // virtual
721 uno::Reference< ucb::XContent > SAL_CALL
722 Content::createNewContent( const ucb::ContentInfo& Info )
723 throw( uno::RuntimeException )
725 if ( isFolder() )
727 osl::Guard< osl::Mutex > aGuard( m_aMutex );
729 if ( Info.Type.isEmpty() )
730 return uno::Reference< ucb::XContent >();
732 if ( !Info.Type.equalsIgnoreAsciiCase(
733 getContentType( m_aUri.getScheme(), sal_True ) ) &&
734 !Info.Type.equalsIgnoreAsciiCase(
735 getContentType( m_aUri.getScheme(), sal_False ) ) )
736 return uno::Reference< ucb::XContent >();
738 rtl::OUString aURL = m_aUri.getUri();
739 aURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
741 if ( Info.Type.equalsIgnoreAsciiCase(
742 getContentType( m_aUri.getScheme(), sal_True ) ) )
743 aURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("New_Folder"));
744 else
745 aURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("New_Stream"));
747 uno::Reference< ucb::XContentIdentifier > xId(
748 new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) );
750 return create( m_xSMgr, m_pProvider, xId, Info );
752 else
754 OSL_FAIL( "createNewContent called on non-folder object!" );
755 return uno::Reference< ucb::XContent >();
759 //=========================================================================
761 // Non-interface methods.
763 //=========================================================================
765 // virtual
766 rtl::OUString Content::getParentURL()
768 return m_aUri.getParentUri();
771 //=========================================================================
772 // static
773 uno::Reference< sdbc::XRow > Content::getPropertyValues(
774 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
775 const uno::Sequence< beans::Property >& rProperties,
776 ContentProvider* pProvider,
777 const rtl::OUString& rContentId )
779 ContentProperties aData;
780 uno::Reference< container::XHierarchicalNameAccess > xPackage;
781 if ( loadData( pProvider, PackageUri( rContentId ), aData, xPackage ) )
783 return getPropertyValues( rSMgr,
784 rProperties,
785 aData,
786 rtl::Reference<
787 ::ucbhelper::ContentProviderImplHelper >(
788 pProvider ),
789 rContentId );
791 else
793 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
794 = new ::ucbhelper::PropertyValueSet( rSMgr );
796 sal_Int32 nCount = rProperties.getLength();
797 if ( nCount )
799 const beans::Property* pProps = rProperties.getConstArray();
800 for ( sal_Int32 n = 0; n < nCount; ++n )
801 xRow->appendVoid( pProps[ n ] );
804 return uno::Reference< sdbc::XRow >( xRow.get() );
808 //=========================================================================
809 // static
810 uno::Reference< sdbc::XRow > Content::getPropertyValues(
811 const uno::Reference< lang::XMultiServiceFactory >& rSMgr,
812 const uno::Sequence< beans::Property >& rProperties,
813 const ContentProperties& rData,
814 const rtl::Reference< ::ucbhelper::ContentProviderImplHelper >&
815 rProvider,
816 const rtl::OUString& rContentId )
818 // Note: Empty sequence means "get values of all supported properties".
820 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
821 = new ::ucbhelper::PropertyValueSet( rSMgr );
823 sal_Int32 nCount = rProperties.getLength();
824 if ( nCount )
826 uno::Reference< beans::XPropertySet > xAdditionalPropSet;
827 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
829 const beans::Property* pProps = rProperties.getConstArray();
830 for ( sal_Int32 n = 0; n < nCount; ++n )
832 const beans::Property& rProp = pProps[ n ];
834 // Process Core properties.
836 if ( rProp.Name == "ContentType" )
838 xRow->appendString ( rProp, rData.aContentType );
840 else if ( rProp.Name == "Title" )
842 xRow->appendString ( rProp, rData.aTitle );
844 else if ( rProp.Name == "IsDocument" )
846 xRow->appendBoolean( rProp, rData.bIsDocument );
848 else if ( rProp.Name == "IsFolder" )
850 xRow->appendBoolean( rProp, rData.bIsFolder );
852 else if ( rProp.Name == "CreatableContentsInfo" )
854 xRow->appendObject(
855 rProp, uno::makeAny(
856 rData.getCreatableContentsInfo(
857 PackageUri( rContentId ) ) ) );
859 else if ( rProp.Name == "MediaType" )
861 xRow->appendString ( rProp, rData.aMediaType );
863 else if ( rProp.Name == "Size" )
865 // Property only available for streams.
866 if ( rData.bIsDocument )
867 xRow->appendLong( rProp, rData.nSize );
868 else
869 xRow->appendVoid( rProp );
871 else if ( rProp.Name == "Compressed" )
873 // Property only available for streams.
874 if ( rData.bIsDocument )
875 xRow->appendBoolean( rProp, rData.bCompressed );
876 else
877 xRow->appendVoid( rProp );
879 else if ( rProp.Name == "Encrypted" )
881 // Property only available for streams.
882 if ( rData.bIsDocument )
883 xRow->appendBoolean( rProp, rData.bEncrypted );
884 else
885 xRow->appendVoid( rProp );
887 else if ( rProp.Name == "HasEncryptedEntries" )
889 // Property only available for root folder.
890 PackageUri aURI( rContentId );
891 if ( aURI.isRootFolder() )
892 xRow->appendBoolean( rProp, rData.bHasEncryptedEntries );
893 else
894 xRow->appendVoid( rProp );
896 else
898 // Not a Core Property! Maybe it's an Additional Core Property?!
900 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
902 xAdditionalPropSet
903 = uno::Reference< beans::XPropertySet >(
904 rProvider->getAdditionalPropertySet( rContentId,
905 sal_False ),
906 uno::UNO_QUERY );
907 bTriedToGetAdditonalPropSet = sal_True;
910 if ( xAdditionalPropSet.is() )
912 if ( !xRow->appendPropertySetValue(
913 xAdditionalPropSet,
914 rProp ) )
916 // Append empty entry.
917 xRow->appendVoid( rProp );
920 else
922 // Append empty entry.
923 xRow->appendVoid( rProp );
928 else
930 // Append all Core Properties.
931 xRow->appendString (
932 beans::Property(
933 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ContentType")),
935 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
936 beans::PropertyAttribute::BOUND
937 | beans::PropertyAttribute::READONLY ),
938 rData.aContentType );
939 xRow->appendString(
940 beans::Property(
941 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title")),
943 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
944 beans::PropertyAttribute::BOUND ),
945 rData.aTitle );
946 xRow->appendBoolean(
947 beans::Property(
948 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsDocument")),
950 getCppuBooleanType(),
951 beans::PropertyAttribute::BOUND
952 | beans::PropertyAttribute::READONLY ),
953 rData.bIsDocument );
954 xRow->appendBoolean(
955 beans::Property(
956 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("IsFolder")),
958 getCppuBooleanType(),
959 beans::PropertyAttribute::BOUND
960 | beans::PropertyAttribute::READONLY ),
961 rData.bIsFolder );
962 xRow->appendObject(
963 beans::Property(
964 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("CreatableContentsInfo")),
966 getCppuType( static_cast<
967 const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
968 beans::PropertyAttribute::BOUND
969 | beans::PropertyAttribute::READONLY ),
970 uno::makeAny(
971 rData.getCreatableContentsInfo( PackageUri( rContentId ) ) ) );
972 xRow->appendString(
973 beans::Property(
974 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MediaType")),
976 getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
977 beans::PropertyAttribute::BOUND ),
978 rData.aMediaType );
980 // Properties only available for streams.
981 if ( rData.bIsDocument )
983 xRow->appendLong(
984 beans::Property(
985 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Size")),
987 getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
988 beans::PropertyAttribute::BOUND
989 | beans::PropertyAttribute::READONLY ),
990 rData.nSize );
992 xRow->appendBoolean(
993 beans::Property(
994 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Compressed")),
996 getCppuBooleanType(),
997 beans::PropertyAttribute::BOUND ),
998 rData.bCompressed );
1000 xRow->appendBoolean(
1001 beans::Property(
1002 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Encrypted")),
1004 getCppuBooleanType(),
1005 beans::PropertyAttribute::BOUND ),
1006 rData.bEncrypted );
1009 // Properties only available for root folder.
1010 PackageUri aURI( rContentId );
1011 if ( aURI.isRootFolder() )
1013 xRow->appendBoolean(
1014 beans::Property(
1015 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasEncryptedEntries")),
1017 getCppuBooleanType(),
1018 beans::PropertyAttribute::BOUND
1019 | beans::PropertyAttribute::READONLY ),
1020 rData.bHasEncryptedEntries );
1023 // Append all Additional Core Properties.
1025 uno::Reference< beans::XPropertySet > xSet(
1026 rProvider->getAdditionalPropertySet( rContentId, sal_False ),
1027 uno::UNO_QUERY );
1028 xRow->appendPropertySet( xSet );
1031 return uno::Reference< sdbc::XRow >( xRow.get() );
1034 //=========================================================================
1035 uno::Reference< sdbc::XRow > Content::getPropertyValues(
1036 const uno::Sequence< beans::Property >& rProperties )
1038 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1039 return getPropertyValues( m_xSMgr,
1040 rProperties,
1041 m_aProps,
1042 rtl::Reference<
1043 ::ucbhelper::ContentProviderImplHelper >(
1044 m_xProvider.get() ),
1045 m_xIdentifier->getContentIdentifier() );
1048 //=========================================================================
1049 uno::Sequence< uno::Any > Content::setPropertyValues(
1050 const uno::Sequence< beans::PropertyValue >& rValues,
1051 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1052 throw( uno::Exception )
1054 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1056 uno::Sequence< uno::Any > aRet( rValues.getLength() );
1057 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
1058 sal_Int32 nChanged = 0;
1060 beans::PropertyChangeEvent aEvent;
1061 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
1062 aEvent.Further = sal_False;
1063 // aEvent.PropertyName =
1064 aEvent.PropertyHandle = -1;
1065 // aEvent.OldValue =
1066 // aEvent.NewValue =
1068 const beans::PropertyValue* pValues = rValues.getConstArray();
1069 sal_Int32 nCount = rValues.getLength();
1071 uno::Reference< ucb::XPersistentPropertySet > xAdditionalPropSet;
1072 sal_Bool bTriedToGetAdditonalPropSet = sal_False;
1073 sal_Bool bExchange = sal_False;
1074 sal_Bool bStore = sal_False;
1075 rtl::OUString aNewTitle;
1076 sal_Int32 nTitlePos = -1;
1078 for ( sal_Int32 n = 0; n < nCount; ++n )
1080 const beans::PropertyValue& rValue = pValues[ n ];
1082 if ( rValue.Name == "ContentType" )
1084 // Read-only property!
1085 aRet[ n ] <<= lang::IllegalAccessException(
1086 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1087 "Property is read-only!" )),
1088 static_cast< cppu::OWeakObject * >( this ) );
1090 else if ( rValue.Name == "IsDocument" )
1092 // Read-only property!
1093 aRet[ n ] <<= lang::IllegalAccessException(
1094 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1095 "Property is read-only!" )),
1096 static_cast< cppu::OWeakObject * >( this ) );
1098 else if ( rValue.Name == "IsFolder" )
1100 // Read-only property!
1101 aRet[ n ] <<= lang::IllegalAccessException(
1102 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1103 "Property is read-only!" )),
1104 static_cast< cppu::OWeakObject * >( this ) );
1106 else if ( rValue.Name == "CreatableContentsInfo" )
1108 // Read-only property!
1109 aRet[ n ] <<= lang::IllegalAccessException(
1110 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1111 "Property is read-only!" )),
1112 static_cast< cppu::OWeakObject * >( this ) );
1114 else if ( rValue.Name == "Title" )
1116 if ( m_aUri.isRootFolder() )
1118 // Read-only property!
1119 aRet[ n ] <<= lang::IllegalAccessException(
1120 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1121 "Property is read-only!" )),
1122 static_cast< cppu::OWeakObject * >( this ) );
1124 else
1126 rtl::OUString aNewValue;
1127 if ( rValue.Value >>= aNewValue )
1129 // No empty titles!
1130 if ( !aNewValue.isEmpty() )
1132 if ( aNewValue != m_aProps.aTitle )
1134 // modified title -> modified URL -> exchange !
1135 if ( m_eState == PERSISTENT )
1136 bExchange = sal_True;
1138 // new value will be set later...
1139 aNewTitle = aNewValue;
1141 // remember position within sequence of values
1142 // (for error handling).
1143 nTitlePos = n;
1146 else
1148 aRet[ n ] <<=
1149 lang::IllegalArgumentException(
1150 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1151 "Empty title not allowed!" )),
1152 static_cast< cppu::OWeakObject * >( this ),
1153 -1 );
1156 else
1158 aRet[ n ] <<=
1159 beans::IllegalTypeException(
1160 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1161 "Property value has wrong type!" )),
1162 static_cast< cppu::OWeakObject * >( this ) );
1166 else if ( rValue.Name == "MediaType" )
1168 rtl::OUString aNewValue;
1169 if ( rValue.Value >>= aNewValue )
1171 if ( aNewValue != m_aProps.aMediaType )
1173 aEvent.PropertyName = rValue.Name;
1174 aEvent.OldValue = uno::makeAny( m_aProps.aMediaType );
1175 aEvent.NewValue = uno::makeAny( aNewValue );
1177 m_aProps.aMediaType = aNewValue;
1178 nChanged++;
1179 bStore = sal_True;
1180 m_nModifiedProps |= MEDIATYPE_MODIFIED;
1183 else
1185 aRet[ n ] <<= beans::IllegalTypeException(
1186 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1187 "Property value has wrong type!" )),
1188 static_cast< cppu::OWeakObject * >( this ) );
1191 else if ( rValue.Name == "Size" )
1193 // Read-only property!
1194 aRet[ n ] <<= lang::IllegalAccessException(
1195 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1196 "Property is read-only!" )),
1197 static_cast< cppu::OWeakObject * >( this ) );
1199 else if ( rValue.Name == "Compressed" )
1201 // Property only available for streams.
1202 if ( m_aProps.bIsDocument )
1204 sal_Bool bNewValue;
1205 if ( rValue.Value >>= bNewValue )
1207 if ( bNewValue != m_aProps.bCompressed )
1209 aEvent.PropertyName = rValue.Name;
1210 aEvent.OldValue = uno::makeAny( m_aProps.bCompressed );
1211 aEvent.NewValue = uno::makeAny( bNewValue );
1213 m_aProps.bCompressed = bNewValue;
1214 nChanged++;
1215 bStore = sal_True;
1216 m_nModifiedProps |= COMPRESSED_MODIFIED;
1219 else
1221 aRet[ n ] <<= beans::IllegalTypeException(
1222 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1223 "Property value has wrong type!" )),
1224 static_cast< cppu::OWeakObject * >( this ) );
1227 else
1229 aRet[ n ] <<= beans::UnknownPropertyException(
1230 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1231 "Compressed only supported by streams!" )),
1232 static_cast< cppu::OWeakObject * >( this ) );
1235 else if ( rValue.Name == "Encrypted" )
1237 // Property only available for streams.
1238 if ( m_aProps.bIsDocument )
1240 sal_Bool bNewValue;
1241 if ( rValue.Value >>= bNewValue )
1243 if ( bNewValue != m_aProps.bEncrypted )
1245 aEvent.PropertyName = rValue.Name;
1246 aEvent.OldValue = uno::makeAny( m_aProps.bEncrypted );
1247 aEvent.NewValue = uno::makeAny( bNewValue );
1249 m_aProps.bEncrypted = bNewValue;
1250 nChanged++;
1251 bStore = sal_True;
1252 m_nModifiedProps |= ENCRYPTED_MODIFIED;
1255 else
1257 aRet[ n ] <<= beans::IllegalTypeException(
1258 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1259 "Property value has wrong type!" )),
1260 static_cast< cppu::OWeakObject * >( this ) );
1263 else
1265 aRet[ n ] <<= beans::UnknownPropertyException(
1266 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1267 "Encrypted only supported by streams!" )),
1268 static_cast< cppu::OWeakObject * >( this ) );
1271 else if ( rValue.Name == "HasEncryptedEntries" )
1273 // Read-only property!
1274 aRet[ n ] <<= lang::IllegalAccessException(
1275 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1276 "Property is read-only!" )),
1277 static_cast< cppu::OWeakObject * >( this ) );
1279 else if ( rValue.Name == "EncryptionKey" )
1281 // @@@ This is a temporary solution. In the future submitting
1282 // the key should be done using an interaction handler!
1284 // Write-Only property. Only supported by root folder and streams
1285 // (all non-root folders of a package have the same encryption key).
1286 if ( m_aUri.isRootFolder() || m_aProps.bIsDocument )
1288 uno::Sequence < sal_Int8 > aNewValue;
1289 if ( rValue.Value >>= aNewValue )
1291 if ( aNewValue != m_aProps.aEncryptionKey )
1293 aEvent.PropertyName = rValue.Name;
1294 aEvent.OldValue = uno::makeAny(
1295 m_aProps.aEncryptionKey );
1296 aEvent.NewValue = uno::makeAny( aNewValue );
1298 m_aProps.aEncryptionKey = aNewValue;
1299 nChanged++;
1300 bStore = sal_True;
1301 m_nModifiedProps |= ENCRYPTIONKEY_MODIFIED;
1304 else
1306 aRet[ n ] <<= beans::IllegalTypeException(
1307 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1308 "Property value has wrong type!" )),
1309 static_cast< cppu::OWeakObject * >( this ) );
1312 else
1314 aRet[ n ] <<= beans::UnknownPropertyException(
1315 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1316 "EncryptionKey not supported by non-root folder!" )),
1317 static_cast< cppu::OWeakObject * >( this ) );
1320 else
1322 // Not a Core Property! Maybe it's an Additional Core Property?!
1324 if ( !bTriedToGetAdditonalPropSet && !xAdditionalPropSet.is() )
1326 xAdditionalPropSet = getAdditionalPropertySet( sal_False );
1327 bTriedToGetAdditonalPropSet = sal_True;
1330 if ( xAdditionalPropSet.is() )
1334 uno::Any aOldValue
1335 = xAdditionalPropSet->getPropertyValue( rValue.Name );
1336 if ( aOldValue != rValue.Value )
1338 xAdditionalPropSet->setPropertyValue(
1339 rValue.Name, rValue.Value );
1341 aEvent.PropertyName = rValue.Name;
1342 aEvent.OldValue = aOldValue;
1343 aEvent.NewValue = rValue.Value;
1345 aChanges.getArray()[ nChanged ] = aEvent;
1346 nChanged++;
1349 catch ( beans::UnknownPropertyException const & e )
1351 aRet[ n ] <<= e;
1353 catch ( lang::WrappedTargetException const & e )
1355 aRet[ n ] <<= e;
1357 catch ( beans::PropertyVetoException const & e )
1359 aRet[ n ] <<= e;
1361 catch ( lang::IllegalArgumentException const & e )
1363 aRet[ n ] <<= e;
1366 else
1368 aRet[ n ] <<= uno::Exception(
1369 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1370 "No property set for storing the value!" )),
1371 static_cast< cppu::OWeakObject * >( this ) );
1376 if ( bExchange )
1378 uno::Reference< ucb::XContentIdentifier > xOldId = m_xIdentifier;
1380 // Assemble new content identifier...
1381 rtl::OUString aNewURL = m_aUri.getParentUri();
1382 aNewURL += rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/"));
1383 aNewURL += ::ucb_impl::urihelper::encodeSegment( aNewTitle );
1384 uno::Reference< ucb::XContentIdentifier > xNewId
1385 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL );
1387 aGuard.clear();
1388 if ( exchangeIdentity( xNewId ) )
1390 // Adapt persistent data.
1391 renameData( xOldId, xNewId );
1393 // Adapt Additional Core Properties.
1394 renameAdditionalPropertySet( xOldId->getContentIdentifier(),
1395 xNewId->getContentIdentifier(),
1396 sal_True );
1398 else
1400 // Do not set new title!
1401 aNewTitle = rtl::OUString();
1403 // Set error .
1404 aRet[ nTitlePos ] <<= uno::Exception(
1405 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Exchange failed!")),
1406 static_cast< cppu::OWeakObject * >( this ) );
1410 if ( !aNewTitle.isEmpty() )
1412 aEvent.PropertyName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title"));
1413 aEvent.OldValue = uno::makeAny( m_aProps.aTitle );
1414 aEvent.NewValue = uno::makeAny( aNewTitle );
1416 m_aProps.aTitle = aNewTitle;
1418 aChanges.getArray()[ nChanged ] = aEvent;
1419 nChanged++;
1422 if ( nChanged > 0 )
1424 // Save changes, if content was already made persistent.
1425 if ( ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED ) ||
1426 ( bStore && ( m_eState == PERSISTENT ) ) )
1428 if ( !storeData( uno::Reference< io::XInputStream >() ) )
1430 uno::Any aProps
1431 = uno::makeAny(
1432 beans::PropertyValue(
1433 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1434 "Uri")),
1436 uno::makeAny(m_xIdentifier->
1437 getContentIdentifier()),
1438 beans::PropertyState_DIRECT_VALUE));
1439 ucbhelper::cancelCommandExecution(
1440 ucb::IOErrorCode_CANT_WRITE,
1441 uno::Sequence< uno::Any >(&aProps, 1),
1442 xEnv,
1443 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1444 "Cannot store persistent data!" )),
1445 this );
1446 // Unreachable
1450 aGuard.clear();
1451 aChanges.realloc( nChanged );
1452 notifyPropertiesChange( aChanges );
1455 return aRet;
1458 //=========================================================================
1459 uno::Any Content::open(
1460 const ucb::OpenCommandArgument2& rArg,
1461 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1462 throw( uno::Exception )
1464 if ( rArg.Mode == ucb::OpenMode::ALL ||
1465 rArg.Mode == ucb::OpenMode::FOLDERS ||
1466 rArg.Mode == ucb::OpenMode::DOCUMENTS )
1468 //////////////////////////////////////////////////////////////////
1469 // open command for a folder content
1470 //////////////////////////////////////////////////////////////////
1472 uno::Reference< ucb::XDynamicResultSet > xSet
1473 = new DynamicResultSet( m_xSMgr, this, rArg, xEnv );
1474 return uno::makeAny( xSet );
1476 else
1478 //////////////////////////////////////////////////////////////////
1479 // open command for a document content
1480 //////////////////////////////////////////////////////////////////
1482 if ( ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
1483 ( rArg.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) )
1485 // Currently(?) unsupported.
1486 ucbhelper::cancelCommandExecution(
1487 uno::makeAny( ucb::UnsupportedOpenModeException(
1488 rtl::OUString(),
1489 static_cast< cppu::OWeakObject * >( this ),
1490 sal_Int16( rArg.Mode ) ) ),
1491 xEnv );
1492 // Unreachable
1495 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
1496 uno::Reference< io::XOutputStream > xOut( rArg.Sink, uno::UNO_QUERY );
1497 if ( xOut.is() )
1499 // PUSH: write data into xOut
1501 uno::Reference< io::XInputStream > xIn = getInputStream();
1502 if ( !xIn.is() )
1504 // No interaction if we are not persistent!
1505 uno::Any aProps
1506 = uno::makeAny(
1507 beans::PropertyValue(
1508 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1509 "Uri")),
1511 uno::makeAny(m_xIdentifier->
1512 getContentIdentifier()),
1513 beans::PropertyState_DIRECT_VALUE));
1514 ucbhelper::cancelCommandExecution(
1515 ucb::IOErrorCode_CANT_READ,
1516 uno::Sequence< uno::Any >(&aProps, 1),
1517 m_eState == PERSISTENT
1518 ? xEnv
1519 : uno::Reference< ucb::XCommandEnvironment >(),
1520 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Got no data stream!")),
1521 this );
1522 // Unreachable
1527 uno::Sequence< sal_Int8 > aBuffer;
1528 sal_Int32 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1530 while ( nRead > 0 )
1532 aBuffer.realloc( nRead );
1533 xOut->writeBytes( aBuffer );
1534 aBuffer.realloc( 0 );
1535 nRead = xIn->readSomeBytes( aBuffer, 65536 );
1538 xOut->closeOutput();
1540 catch ( io::NotConnectedException const & )
1542 // closeOutput, readSomeBytes, writeBytes
1544 catch ( io::BufferSizeExceededException const & )
1546 // closeOutput, readSomeBytes, writeBytes
1548 catch ( io::IOException const & )
1550 // closeOutput, readSomeBytes, writeBytes
1553 else
1555 uno::Reference< io::XActiveDataSink > xDataSink(
1556 rArg.Sink, uno::UNO_QUERY );
1557 if ( xDataSink.is() )
1559 // PULL: wait for client read
1561 uno::Reference< io::XInputStream > xIn = getInputStream();
1562 if ( !xIn.is() )
1564 // No interaction if we are not persistent!
1565 uno::Any aProps
1566 = uno::makeAny(
1567 beans::PropertyValue(
1568 rtl::OUString( "Uri"),
1570 uno::makeAny(m_xIdentifier->
1571 getContentIdentifier()),
1572 beans::PropertyState_DIRECT_VALUE));
1573 ucbhelper::cancelCommandExecution(
1574 ucb::IOErrorCode_CANT_READ,
1575 uno::Sequence< uno::Any >(&aProps, 1),
1576 m_eState == PERSISTENT
1577 ? xEnv
1578 : uno::Reference<
1579 ucb::XCommandEnvironment >(),
1580 rtl::OUString( "Got no data stream!" ),
1581 this );
1582 // Unreachable
1585 // Done.
1586 xDataSink->setInputStream( xIn );
1588 else
1590 // Note: aOpenCommand.Sink may contain an XStream
1591 // implementation. Support for this type of
1592 // sink is optional...
1593 ucbhelper::cancelCommandExecution(
1594 uno::makeAny(
1595 ucb::UnsupportedDataSinkException(
1596 rtl::OUString(),
1597 static_cast< cppu::OWeakObject * >( this ),
1598 rArg.Sink ) ),
1599 xEnv );
1600 // Unreachable
1605 return uno::Any();
1608 //=========================================================================
1609 void Content::insert(
1610 const uno::Reference< io::XInputStream >& xStream,
1611 sal_Int32 nNameClashResolve,
1612 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1613 throw( uno::Exception )
1615 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1617 // Check, if all required properties were set.
1618 if ( isFolder() )
1620 // Required: Title
1622 if ( m_aProps.aTitle.isEmpty() )
1623 m_aProps.aTitle = m_aUri.getName();
1625 else
1627 // Required: rArg.Data
1629 if ( !xStream.is() )
1631 ucbhelper::cancelCommandExecution(
1632 uno::makeAny( ucb::MissingInputStreamException(
1633 rtl::OUString(),
1634 static_cast< cppu::OWeakObject * >( this ) ) ),
1635 xEnv );
1636 // Unreachable
1639 // Required: Title
1641 if ( m_aProps.aTitle.isEmpty() )
1642 m_aProps.aTitle = m_aUri.getName();
1645 rtl::OUString aNewURL = m_aUri.getParentUri();
1646 if (1 + aNewURL.lastIndexOf('/') != aNewURL.getLength())
1647 aNewURL += rtl::OUString("/");
1648 aNewURL += ::ucb_impl::urihelper::encodeSegment( m_aProps.aTitle );
1649 PackageUri aNewUri( aNewURL );
1651 // Handle possible name clash...
1652 switch ( nNameClashResolve )
1654 // fail.
1655 case ucb::NameClash::ERROR:
1656 if ( hasData( aNewUri ) )
1658 ucbhelper::cancelCommandExecution(
1659 uno::makeAny( ucb::NameClashException(
1660 rtl::OUString(),
1661 static_cast< cppu::OWeakObject * >( this ),
1662 task::InteractionClassification_ERROR,
1663 m_aProps.aTitle ) ),
1664 xEnv );
1665 // Unreachable
1667 break;
1669 // replace (possibly) existing object.
1670 case ucb::NameClash::OVERWRITE:
1671 break;
1673 // "invent" a new valid title.
1674 case ucb::NameClash::RENAME:
1675 if ( hasData( aNewUri ) )
1677 sal_Int32 nTry = 0;
1681 rtl::OUString aNew = aNewUri.getUri();
1682 aNew += rtl::OUString("_");
1683 aNew += rtl::OUString::valueOf( ++nTry );
1684 aNewUri.setUri( aNew );
1686 while ( hasData( aNewUri ) && ( nTry < 1000 ) );
1688 if ( nTry == 1000 )
1690 ucbhelper::cancelCommandExecution(
1691 uno::makeAny(
1692 ucb::UnsupportedNameClashException(
1693 rtl::OUString( "Unable to resolve name clash!" ),
1694 static_cast< cppu::OWeakObject * >( this ),
1695 nNameClashResolve ) ),
1696 xEnv );
1697 // Unreachable
1699 else
1701 m_aProps.aTitle += rtl::OUString("_");
1702 m_aProps.aTitle += rtl::OUString::valueOf( nTry );
1705 break;
1707 case ucb::NameClash::KEEP: // deprecated
1708 case ucb::NameClash::ASK:
1709 default:
1710 if ( hasData( aNewUri ) )
1712 ucbhelper::cancelCommandExecution(
1713 uno::makeAny(
1714 ucb::UnsupportedNameClashException(
1715 rtl::OUString(),
1716 static_cast< cppu::OWeakObject * >( this ),
1717 nNameClashResolve ) ),
1718 xEnv );
1719 // Unreachable
1721 break;
1724 // Identifier changed?
1725 sal_Bool bNewId = ( m_aUri.getUri() != aNewUri.getUri() );
1727 if ( bNewId )
1729 m_xIdentifier = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewURL );
1730 m_aUri = aNewUri;
1733 if ( !storeData( xStream ) )
1735 uno::Any aProps
1736 = uno::makeAny(beans::PropertyValue(
1737 rtl::OUString( "Uri"),
1739 uno::makeAny(m_xIdentifier->
1740 getContentIdentifier()),
1741 beans::PropertyState_DIRECT_VALUE));
1742 ucbhelper::cancelCommandExecution(
1743 ucb::IOErrorCode_CANT_WRITE,
1744 uno::Sequence< uno::Any >(&aProps, 1),
1745 xEnv,
1746 rtl::OUString("Cannot store persistent data!"),
1747 this );
1748 // Unreachable
1751 m_eState = PERSISTENT;
1753 if ( bNewId )
1755 // Take over correct default values from underlying packager...
1756 uno::Reference< container::XHierarchicalNameAccess > xXHierarchicalNameAccess;
1757 loadData( m_pProvider,
1758 m_aUri,
1759 m_aProps,
1760 xXHierarchicalNameAccess );
1762 aGuard.clear();
1763 inserted();
1767 //=========================================================================
1768 void Content::destroy(
1769 sal_Bool bDeletePhysical,
1770 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1771 throw( uno::Exception )
1773 // @@@ take care about bDeletePhysical -> trashcan support
1775 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1777 uno::Reference< ucb::XContent > xThis = this;
1779 // Persistent?
1780 if ( m_eState != PERSISTENT )
1782 ucbhelper::cancelCommandExecution(
1783 uno::makeAny( ucb::UnsupportedCommandException(
1784 rtl::OUString( "Not persistent!" ),
1785 static_cast< cppu::OWeakObject * >( this ) ) ),
1786 xEnv );
1787 // Unreachable
1790 m_eState = DEAD;
1792 aGuard.clear();
1793 deleted();
1795 if ( isFolder() )
1797 // Process instanciated children...
1799 ContentRefList aChildren;
1800 queryChildren( aChildren );
1802 ContentRefList::const_iterator it = aChildren.begin();
1803 ContentRefList::const_iterator end = aChildren.end();
1805 while ( it != end )
1807 (*it)->destroy( bDeletePhysical, xEnv );
1808 ++it;
1813 //=========================================================================
1814 void Content::transfer(
1815 const ucb::TransferInfo& rInfo,
1816 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1817 throw( uno::Exception )
1819 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
1821 // Persistent?
1822 if ( m_eState != PERSISTENT )
1824 ucbhelper::cancelCommandExecution(
1825 uno::makeAny( ucb::UnsupportedCommandException(
1826 rtl::OUString( "Not persistent!" ),
1827 static_cast< cppu::OWeakObject * >( this ) ) ),
1828 xEnv );
1829 // Unreachable
1832 // Is source a package content?
1833 if ( ( rInfo.SourceURL.isEmpty() ) ||
1834 ( rInfo.SourceURL.compareTo(
1835 m_aUri.getUri(), PACKAGE_URL_SCHEME_LENGTH + 3 ) != 0 ) )
1837 ucbhelper::cancelCommandExecution(
1838 uno::makeAny( ucb::InteractiveBadTransferURLException(
1839 rtl::OUString(),
1840 static_cast< cppu::OWeakObject * >( this ) ) ),
1841 xEnv );
1842 // Unreachable
1845 // Is source not a parent of me / not me?
1846 rtl::OUString aId = m_aUri.getParentUri();
1847 aId += rtl::OUString("/");
1849 if ( rInfo.SourceURL.getLength() <= aId.getLength() )
1851 if ( aId.compareTo(
1852 rInfo.SourceURL, rInfo.SourceURL.getLength() ) == 0 )
1854 uno::Any aProps
1855 = uno::makeAny(beans::PropertyValue(
1856 rtl::OUString( "Uri"),
1858 uno::makeAny(rInfo.SourceURL),
1859 beans::PropertyState_DIRECT_VALUE));
1860 ucbhelper::cancelCommandExecution(
1861 ucb::IOErrorCode_RECURSIVE,
1862 uno::Sequence< uno::Any >(&aProps, 1),
1863 xEnv,
1864 rtl::OUString( "Target is equal to or is a child of source!" ),
1865 this );
1866 // Unreachable
1870 //////////////////////////////////////////////////////////////////////
1871 // 0) Obtain content object for source.
1872 //////////////////////////////////////////////////////////////////////
1874 uno::Reference< ucb::XContentIdentifier > xId
1875 = new ::ucbhelper::ContentIdentifier( m_xSMgr, rInfo.SourceURL );
1877 // Note: The static cast is okay here, because its sure that
1878 // m_xProvider is always the PackageContentProvider.
1879 rtl::Reference< Content > xSource;
1883 xSource = static_cast< Content * >(
1884 m_xProvider->queryContent( xId ).get() );
1886 catch ( ucb::IllegalIdentifierException const & )
1888 // queryContent
1891 if ( !xSource.is() )
1893 uno::Any aProps
1894 = uno::makeAny(beans::PropertyValue(
1895 rtl::OUString( "Uri"),
1897 uno::makeAny(xId->getContentIdentifier()),
1898 beans::PropertyState_DIRECT_VALUE));
1899 ucbhelper::cancelCommandExecution(
1900 ucb::IOErrorCode_CANT_READ,
1901 uno::Sequence< uno::Any >(&aProps, 1),
1902 xEnv,
1903 rtl::OUString( "Cannot instanciate source object!" ),
1904 this );
1905 // Unreachable
1908 //////////////////////////////////////////////////////////////////////
1909 // 1) Create new child content.
1910 //////////////////////////////////////////////////////////////////////
1912 rtl::OUString aType = xSource->isFolder()
1913 ? getContentType( m_aUri.getScheme(), sal_True )
1914 : getContentType( m_aUri.getScheme(), sal_False );
1915 ucb::ContentInfo aContentInfo;
1916 aContentInfo.Type = aType;
1917 aContentInfo.Attributes = 0;
1919 // Note: The static cast is okay here, because its sure that
1920 // createNewContent always creates a Content.
1921 rtl::Reference< Content > xTarget
1922 = static_cast< Content * >( createNewContent( aContentInfo ).get() );
1923 if ( !xTarget.is() )
1925 uno::Any aProps
1926 = uno::makeAny(beans::PropertyValue(
1927 rtl::OUString( "Folder"),
1929 uno::makeAny(aId),
1930 beans::PropertyState_DIRECT_VALUE));
1931 ucbhelper::cancelCommandExecution(
1932 ucb::IOErrorCode_CANT_CREATE,
1933 uno::Sequence< uno::Any >(&aProps, 1),
1934 xEnv,
1935 rtl::OUString( "XContentCreator::createNewContent failed!" ),
1936 this );
1937 // Unreachable
1940 //////////////////////////////////////////////////////////////////////
1941 // 2) Copy data from source content to child content.
1942 //////////////////////////////////////////////////////////////////////
1944 uno::Sequence< beans::Property > aSourceProps
1945 = xSource->getPropertySetInfo( xEnv )->getProperties();
1946 sal_Int32 nCount = aSourceProps.getLength();
1948 if ( nCount )
1950 sal_Bool bHadTitle = rInfo.NewTitle.isEmpty();
1952 // Get all source values.
1953 uno::Reference< sdbc::XRow > xRow
1954 = xSource->getPropertyValues( aSourceProps );
1956 uno::Sequence< beans::PropertyValue > aValues( nCount );
1957 beans::PropertyValue* pValues = aValues.getArray();
1959 const beans::Property* pProps = aSourceProps.getConstArray();
1960 for ( sal_Int32 n = 0; n < nCount; ++n )
1962 const beans::Property& rProp = pProps[ n ];
1963 beans::PropertyValue& rValue = pValues[ n ];
1965 rValue.Name = rProp.Name;
1966 rValue.Handle = rProp.Handle;
1968 if ( !bHadTitle && rProp.Name == "Title" )
1970 // Set new title instead of original.
1971 bHadTitle = sal_True;
1972 rValue.Value <<= rInfo.NewTitle;
1974 else
1975 rValue.Value
1976 = xRow->getObject( n + 1,
1977 uno::Reference<
1978 container::XNameAccess >() );
1980 rValue.State = beans::PropertyState_DIRECT_VALUE;
1982 if ( rProp.Attributes & beans::PropertyAttribute::REMOVABLE )
1984 // Add Additional Core Property.
1987 xTarget->addProperty( rProp.Name,
1988 rProp.Attributes,
1989 rValue.Value );
1991 catch ( beans::PropertyExistException const & )
1994 catch ( beans::IllegalTypeException const & )
1997 catch ( lang::IllegalArgumentException const & )
2003 // Set target values.
2004 xTarget->setPropertyValues( aValues, xEnv );
2007 //////////////////////////////////////////////////////////////////////
2008 // 3) Commit (insert) child.
2009 //////////////////////////////////////////////////////////////////////
2011 xTarget->insert( xSource->getInputStream(), rInfo.NameClash, xEnv );
2013 //////////////////////////////////////////////////////////////////////
2014 // 4) Transfer (copy) children of source.
2015 //////////////////////////////////////////////////////////////////////
2017 if ( xSource->isFolder() )
2019 uno::Reference< container::XEnumeration > xIter
2020 = xSource->getIterator();
2021 if ( xIter.is() )
2023 while ( xIter->hasMoreElements() )
2027 uno::Reference< container::XNamed > xNamed;
2028 xIter->nextElement() >>= xNamed;
2030 if ( !xNamed.is() )
2032 OSL_FAIL( "Content::transfer - Got no XNamed!" );
2033 break;
2036 rtl::OUString aName = xNamed->getName();
2038 if ( aName.isEmpty() )
2040 OSL_FAIL( "Content::transfer - Empty name!" );
2041 break;
2044 rtl::OUString aChildId = xId->getContentIdentifier();
2045 if ( ( aChildId.lastIndexOf( '/' ) + 1 )
2046 != aChildId.getLength() )
2047 aChildId += rtl::OUString("/");
2049 aChildId += ::ucb_impl::urihelper::encodeSegment( aName );
2051 ucb::TransferInfo aInfo;
2052 aInfo.MoveData = sal_False;
2053 aInfo.NewTitle = rtl::OUString();
2054 aInfo.SourceURL = aChildId;
2055 aInfo.NameClash = rInfo.NameClash;
2057 // Transfer child to target.
2058 xTarget->transfer( aInfo, xEnv );
2060 catch ( container::NoSuchElementException const & )
2063 catch ( lang::WrappedTargetException const & )
2070 //////////////////////////////////////////////////////////////////////
2071 // 5) Destroy source ( when moving only ) .
2072 //////////////////////////////////////////////////////////////////////
2074 if ( rInfo.MoveData )
2076 xSource->destroy( sal_True, xEnv );
2078 // Remove all persistent data of source and its children.
2079 if ( !xSource->removeData() )
2081 uno::Any aProps
2082 = uno::makeAny(
2083 beans::PropertyValue(
2084 rtl::OUString( "Uri"),
2086 uno::makeAny(
2087 xSource->m_xIdentifier->
2088 getContentIdentifier()),
2089 beans::PropertyState_DIRECT_VALUE));
2090 ucbhelper::cancelCommandExecution(
2091 ucb::IOErrorCode_CANT_WRITE,
2092 uno::Sequence< uno::Any >(&aProps, 1),
2093 xEnv,
2094 rtl::OUString( "Cannot remove persistent data of source object!" ),
2095 this );
2096 // Unreachable
2099 // Remove own and all children's Additional Core Properties.
2100 xSource->removeAdditionalPropertySet( sal_True );
2104 //=========================================================================
2105 sal_Bool Content::exchangeIdentity(
2106 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2108 if ( !xNewId.is() )
2109 return sal_False;
2111 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
2113 uno::Reference< ucb::XContent > xThis = this;
2115 // Already persistent?
2116 if ( m_eState != PERSISTENT )
2118 OSL_FAIL( "Content::exchangeIdentity - Not persistent!" );
2119 return sal_False;
2122 // Exchange own identitity.
2124 // Fail, if a content with given id already exists.
2125 PackageUri aNewUri( xNewId->getContentIdentifier() );
2126 if ( !hasData( aNewUri ) )
2128 rtl::OUString aOldURL = m_xIdentifier->getContentIdentifier();
2130 aGuard.clear();
2131 if ( exchange( xNewId ) )
2133 m_aUri = aNewUri;
2134 if ( isFolder() )
2136 // Process instanciated children...
2138 ContentRefList aChildren;
2139 queryChildren( aChildren );
2141 ContentRefList::const_iterator it = aChildren.begin();
2142 ContentRefList::const_iterator end = aChildren.end();
2144 while ( it != end )
2146 ContentRef xChild = (*it);
2148 // Create new content identifier for the child...
2149 uno::Reference< ucb::XContentIdentifier > xOldChildId
2150 = xChild->getIdentifier();
2151 rtl::OUString aOldChildURL
2152 = xOldChildId->getContentIdentifier();
2153 rtl::OUString aNewChildURL
2154 = aOldChildURL.replaceAt(
2156 aOldURL.getLength(),
2157 xNewId->getContentIdentifier() );
2158 uno::Reference< ucb::XContentIdentifier > xNewChildId
2159 = new ::ucbhelper::ContentIdentifier(
2160 m_xSMgr, aNewChildURL );
2162 if ( !xChild->exchangeIdentity( xNewChildId ) )
2163 return sal_False;
2165 ++it;
2168 return sal_True;
2172 OSL_FAIL( "Content::exchangeIdentity - Panic! Cannot exchange identity!" );
2173 return sal_False;
2176 //=========================================================================
2177 void Content::queryChildren( ContentRefList& rChildren )
2179 // Obtain a list with a snapshot of all currently instanciated contents
2180 // from provider and extract the contents which are direct children
2181 // of this content.
2183 ::ucbhelper::ContentRefList aAllContents;
2184 m_xProvider->queryExistingContents( aAllContents );
2186 rtl::OUString aURL = m_xIdentifier->getContentIdentifier();
2188 OSL_ENSURE( aURL.lastIndexOf( '/' ) != ( aURL.getLength() - 1 ),
2189 "Content::queryChildren - Invalid URL!" );
2191 aURL += rtl::OUString("/");
2193 sal_Int32 nLen = aURL.getLength();
2195 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
2196 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
2198 while ( it != end )
2200 ::ucbhelper::ContentImplHelperRef xChild = (*it);
2201 rtl::OUString aChildURL
2202 = xChild->getIdentifier()->getContentIdentifier();
2204 // Is aURL a prefix of aChildURL?
2205 if ( ( aChildURL.getLength() > nLen ) &&
2206 ( aChildURL.compareTo( aURL, nLen ) == 0 ) )
2208 if ( aChildURL.indexOf( '/', nLen ) == -1 )
2210 // No further slashes. It's a child!
2211 rChildren.push_back(
2212 ContentRef(
2213 static_cast< Content * >( xChild.get() ) ) );
2216 ++it;
2220 //=========================================================================
2221 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage(
2222 const PackageUri& rURI )
2224 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2226 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2227 if ( rURI.getPackage() == m_aUri.getPackage() )
2229 if ( !m_xPackage.is() )
2230 m_xPackage = m_pProvider->createPackage( m_aUri.getPackage(), m_aUri.getParam() );
2232 return m_xPackage;
2235 return m_pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2238 //=========================================================================
2239 uno::Reference< container::XHierarchicalNameAccess > Content::getPackage()
2241 return getPackage( m_aUri );
2244 //=========================================================================
2245 // static
2246 sal_Bool Content::hasData(
2247 ContentProvider* pProvider,
2248 const PackageUri& rURI,
2249 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2251 rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2252 if ( !rxPackage.is() )
2253 return sal_False;
2255 return rxPackage->hasByHierarchicalName( rURI.getPath() );
2258 //=========================================================================
2259 sal_Bool Content::hasData( const PackageUri& rURI )
2261 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2263 uno::Reference< container::XHierarchicalNameAccess > xPackage;
2264 if ( rURI.getPackage() == m_aUri.getPackage() )
2266 xPackage = getPackage();
2267 if ( !xPackage.is() )
2268 return sal_False;
2270 return xPackage->hasByHierarchicalName( rURI.getPath() );
2273 return hasData( m_pProvider, rURI, xPackage );
2276 //=========================================================================
2277 //static
2278 sal_Bool Content::loadData(
2279 ContentProvider* pProvider,
2280 const PackageUri& rURI,
2281 ContentProperties& rProps,
2282 uno::Reference< container::XHierarchicalNameAccess > & rxPackage )
2284 rxPackage = pProvider->createPackage( rURI.getPackage(), rURI.getParam() );
2285 if ( !rxPackage.is() )
2286 return sal_False;
2288 if ( rURI.isRootFolder() )
2290 // Properties available only from package
2291 uno::Reference< beans::XPropertySet > xPackagePropSet(
2292 rxPackage, uno::UNO_QUERY );
2294 OSL_ENSURE( xPackagePropSet.is(),
2295 "Content::loadData - "
2296 "Got no XPropertySet interface from package!" );
2298 if ( xPackagePropSet.is() )
2300 // HasEncryptedEntries ( only avalibale at root folder )
2303 uno::Any aHasEncryptedEntries
2304 = xPackagePropSet->getPropertyValue(
2305 rtl::OUString( "HasEncryptedEntries" ) );
2306 if ( !( aHasEncryptedEntries >>= rProps.bHasEncryptedEntries ) )
2308 OSL_FAIL( "Content::loadData - "
2309 "Got no HasEncryptedEntries value!" );
2310 return sal_False;
2313 catch ( beans::UnknownPropertyException const & )
2315 OSL_FAIL( "Content::loadData - "
2316 "Got no HasEncryptedEntries value!" );
2317 return sal_False;
2319 catch ( lang::WrappedTargetException const & )
2321 OSL_FAIL( "Content::loadData - "
2322 "Got no HasEncryptedEntries value!" );
2323 return sal_False;
2328 if ( !rxPackage->hasByHierarchicalName( rURI.getPath() ) )
2329 return sal_False;
2333 uno::Any aEntry = rxPackage->getByHierarchicalName( rURI.getPath() );
2334 if ( aEntry.hasValue() )
2336 uno::Reference< beans::XPropertySet > xPropSet;
2337 aEntry >>= xPropSet;
2339 if ( !xPropSet.is() )
2341 OSL_FAIL( "Content::loadData - Got no XPropertySet interface!" );
2342 return sal_False;
2345 // Title
2346 rProps.aTitle = rURI.getName();
2348 // MediaType
2351 uno::Any aMediaType
2352 = xPropSet->getPropertyValue(
2353 rtl::OUString("MediaType") );
2354 if ( !( aMediaType >>= rProps.aMediaType ) )
2356 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2357 return sal_False;
2360 catch ( beans::UnknownPropertyException const & )
2362 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2363 return sal_False;
2365 catch ( lang::WrappedTargetException const & )
2367 OSL_FAIL( "Content::loadData - Got no MediaType value!" );
2368 return sal_False;
2371 uno::Reference< container::XEnumerationAccess > xEnumAccess;
2372 aEntry >>= xEnumAccess;
2374 // ContentType / IsFolder / IsDocument
2375 if ( xEnumAccess.is() )
2377 // folder
2378 rProps.aContentType = getContentType( rURI.getScheme(), sal_True );
2379 rProps.bIsDocument = sal_False;
2380 rProps.bIsFolder = sal_True;
2382 else
2384 // stream
2385 rProps.aContentType = getContentType( rURI.getScheme(), sal_False );
2386 rProps.bIsDocument = sal_True;
2387 rProps.bIsFolder = sal_False;
2390 if ( rProps.bIsDocument )
2392 // Size ( only available for streams )
2395 uno::Any aSize
2396 = xPropSet->getPropertyValue(
2397 rtl::OUString("Size") );
2398 if ( !( aSize >>= rProps.nSize ) )
2400 OSL_FAIL( "Content::loadData - Got no Size value!" );
2401 return sal_False;
2404 catch ( beans::UnknownPropertyException const & )
2406 OSL_FAIL( "Content::loadData - Got no Size value!" );
2407 return sal_False;
2409 catch ( lang::WrappedTargetException const & )
2411 OSL_FAIL( "Content::loadData - Got no Size value!" );
2412 return sal_False;
2415 // Compressed ( only available for streams )
2418 uno::Any aCompressed
2419 = xPropSet->getPropertyValue(
2420 rtl::OUString("Compressed") );
2421 if ( !( aCompressed >>= rProps.bCompressed ) )
2423 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2424 return sal_False;
2427 catch ( beans::UnknownPropertyException const & )
2429 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2430 return sal_False;
2432 catch ( lang::WrappedTargetException const & )
2434 OSL_FAIL( "Content::loadData - Got no Compressed value!" );
2435 return sal_False;
2438 // Encrypted ( only available for streams )
2441 uno::Any aEncrypted
2442 = xPropSet->getPropertyValue(
2443 rtl::OUString("Encrypted") );
2444 if ( !( aEncrypted >>= rProps.bEncrypted ) )
2446 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2447 return sal_False;
2450 catch ( beans::UnknownPropertyException const & )
2452 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2453 return sal_False;
2455 catch ( lang::WrappedTargetException const & )
2457 OSL_FAIL( "Content::loadData - Got no Encrypted value!" );
2458 return sal_False;
2461 return sal_True;
2464 catch ( container::NoSuchElementException const & )
2466 // getByHierarchicalName
2469 return sal_False;
2472 //=========================================================================
2473 sal_Bool Content::renameData(
2474 const uno::Reference< ucb::XContentIdentifier >& xOldId,
2475 const uno::Reference< ucb::XContentIdentifier >& xNewId )
2477 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2479 PackageUri aURI( xOldId->getContentIdentifier() );
2480 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage(
2481 aURI );
2482 if ( !xNA.is() )
2483 return sal_False;
2485 if ( !xNA->hasByHierarchicalName( aURI.getPath() ) )
2486 return sal_False;
2490 uno::Any aEntry = xNA->getByHierarchicalName( aURI.getPath() );
2491 uno::Reference< container::XNamed > xNamed;
2492 aEntry >>= xNamed;
2494 if ( !xNamed.is() )
2496 OSL_FAIL( "Content::renameData - Got no XNamed interface!" );
2497 return sal_False;
2500 PackageUri aNewURI( xNewId->getContentIdentifier() );
2502 // No success indicator!? No return value / exceptions specified.
2503 xNamed->setName( aNewURI.getName() );
2505 return sal_True;
2507 catch ( container::NoSuchElementException const & )
2509 // getByHierarchicalName
2512 return sal_False;
2515 //=========================================================================
2516 sal_Bool Content::storeData( const uno::Reference< io::XInputStream >& xStream )
2518 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2520 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2521 if ( !xNA.is() )
2522 return sal_False;
2524 uno::Reference< beans::XPropertySet > xPackagePropSet(
2525 xNA, uno::UNO_QUERY );
2526 OSL_ENSURE( xPackagePropSet.is(),
2527 "Content::storeData - "
2528 "Got no XPropertySet interface from package!" );
2530 if ( !xPackagePropSet.is() )
2531 return sal_False;
2533 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2535 if ( m_aUri.isRootFolder() )
2537 // Property available only from package and from streams (see below)
2540 xPackagePropSet->setPropertyValue(
2541 rtl::OUString("EncryptionKey"),
2542 uno::makeAny( m_aProps.aEncryptionKey ) );
2543 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2545 catch ( beans::UnknownPropertyException const & )
2547 // setPropertyValue
2549 catch ( beans::PropertyVetoException const & )
2551 // setPropertyValue
2553 catch ( lang::IllegalArgumentException const & )
2555 // setPropertyValue
2557 catch ( lang::WrappedTargetException const & )
2559 // setPropertyValue
2564 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2566 // if ( !bCreate )
2567 // return sal_True;
2571 // Create new resource...
2572 uno::Reference< lang::XSingleServiceFactory > xFac(
2573 xNA, uno::UNO_QUERY );
2574 if ( !xFac.is() )
2576 OSL_FAIL( "Content::storeData - "
2577 "Got no XSingleServiceFactory interface!" );
2578 return sal_False;
2581 uno::Sequence< uno::Any > aArgs( 1 );
2582 aArgs[ 0 ] <<= isFolder();
2584 uno::Reference< uno::XInterface > xNew
2585 = xFac->createInstanceWithArguments( aArgs );
2587 if ( !xNew.is() )
2589 OSL_FAIL( "Content::storeData - createInstance failed!" );
2590 return sal_False;
2593 PackageUri aParentUri( getParentURL() );
2594 uno::Any aEntry
2595 = xNA->getByHierarchicalName( aParentUri.getPath() );
2596 uno::Reference< container::XNameContainer > xParentContainer;
2597 aEntry >>= xParentContainer;
2599 if ( !xParentContainer.is() )
2601 OSL_FAIL( "Content::storeData - "
2602 "Got no XNameContainer interface!" );
2603 return sal_False;
2606 xParentContainer->insertByName( m_aProps.aTitle,
2607 uno::makeAny( xNew ) );
2609 catch ( uno::RuntimeException const & )
2611 throw;
2613 catch ( lang::IllegalArgumentException const & )
2615 // insertByName
2616 OSL_FAIL( "Content::storeData - insertByName failed!" );
2617 return sal_False;
2619 catch ( container::ElementExistException const & )
2621 // insertByName
2622 OSL_FAIL( "Content::storeData - insertByName failed!" );
2623 return sal_False;
2625 catch ( lang::WrappedTargetException const & )
2627 // insertByName
2628 OSL_FAIL( "Content::storeData - insertByName failed!" );
2629 return sal_False;
2631 catch ( container::NoSuchElementException const & )
2633 // getByHierarchicalName
2634 OSL_FAIL( "Content::storeData - getByHierarchicalName failed!" );
2635 return sal_False;
2637 catch ( uno::Exception const & )
2639 // createInstanceWithArguments
2640 OSL_FAIL( "Content::storeData - Error!" );
2641 return sal_False;
2645 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2646 return sal_False;
2650 uno::Reference< beans::XPropertySet > xPropSet;
2651 xNA->getByHierarchicalName( m_aUri.getPath() ) >>= xPropSet;
2653 if ( !xPropSet.is() )
2655 OSL_FAIL( "Content::storeData - Got no XPropertySet interface!" );
2656 return sal_False;
2659 //////////////////////////////////////////////////////////////////
2660 // Store property values...
2661 //////////////////////////////////////////////////////////////////
2663 if ( m_nModifiedProps & MEDIATYPE_MODIFIED )
2665 xPropSet->setPropertyValue(
2666 rtl::OUString("MediaType"),
2667 uno::makeAny( m_aProps.aMediaType ) );
2668 m_nModifiedProps &= ~MEDIATYPE_MODIFIED;
2671 if ( m_nModifiedProps & COMPRESSED_MODIFIED )
2673 if ( !isFolder() )
2674 xPropSet->setPropertyValue(
2675 rtl::OUString("Compressed"),
2676 uno::makeAny( m_aProps.bCompressed ) );
2678 m_nModifiedProps &= ~COMPRESSED_MODIFIED;
2681 if ( m_nModifiedProps & ENCRYPTED_MODIFIED )
2683 if ( !isFolder() )
2684 xPropSet->setPropertyValue(
2685 rtl::OUString("Encrypted"),
2686 uno::makeAny( m_aProps.bEncrypted ) );
2688 m_nModifiedProps &= ~ENCRYPTED_MODIFIED;
2691 if ( m_nModifiedProps & ENCRYPTIONKEY_MODIFIED )
2693 if ( !isFolder() )
2694 xPropSet->setPropertyValue(
2695 rtl::OUString("EncryptionKey"),
2696 uno::makeAny( m_aProps.aEncryptionKey ) );
2698 m_nModifiedProps &= ~ENCRYPTIONKEY_MODIFIED;
2701 //////////////////////////////////////////////////////////////////
2702 // Store data stream...
2703 //////////////////////////////////////////////////////////////////
2705 if ( xStream.is() && !isFolder() )
2707 uno::Reference< io::XActiveDataSink > xSink(
2708 xPropSet, uno::UNO_QUERY );
2710 if ( !xSink.is() )
2712 OSL_FAIL( "Content::storeData - "
2713 "Got no XActiveDataSink interface!" );
2714 return sal_False;
2717 xSink->setInputStream( xStream );
2720 return sal_True;
2722 catch ( container::NoSuchElementException const & )
2724 // getByHierarchicalName
2726 catch ( beans::UnknownPropertyException const & )
2728 // setPropertyValue
2730 catch ( beans::PropertyVetoException const & )
2732 // setPropertyValue
2734 catch ( lang::IllegalArgumentException const & )
2736 // setPropertyValue
2738 catch ( lang::WrappedTargetException const & )
2740 // setPropertyValue
2743 OSL_FAIL( "Content::storeData - Error!" );
2744 return sal_False;
2747 //=========================================================================
2748 sal_Bool Content::removeData()
2750 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2752 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2753 if ( !xNA.is() )
2754 return sal_False;
2756 PackageUri aParentUri( getParentURL() );
2757 if ( !xNA->hasByHierarchicalName( aParentUri.getPath() ) )
2758 return sal_False;
2762 uno::Any aEntry = xNA->getByHierarchicalName( aParentUri.getPath() );
2763 uno::Reference< container::XNameContainer > xContainer;
2764 aEntry >>= xContainer;
2766 if ( !xContainer.is() )
2768 OSL_FAIL( "Content::removeData - "
2769 "Got no XNameContainer interface!" );
2770 return sal_False;
2773 xContainer->removeByName( m_aUri.getName() );
2774 return sal_True;
2776 catch ( container::NoSuchElementException const & )
2778 // getByHierarchicalName, removeByName
2780 catch ( lang::WrappedTargetException const & )
2782 // removeByName
2785 OSL_FAIL( "Content::removeData - Error!" );
2786 return sal_False;
2789 //=========================================================================
2790 sal_Bool Content::flushData()
2792 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2794 // Note: XChangesBatch is only implemented by the package itself, not
2795 // by the single entries. Maybe this has to change...
2797 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2798 if ( !xNA.is() )
2799 return sal_False;
2801 uno::Reference< util::XChangesBatch > xBatch( xNA, uno::UNO_QUERY );
2802 if ( !xBatch.is() )
2804 OSL_FAIL( "Content::flushData - Got no XChangesBatch interface!" );
2805 return sal_False;
2810 xBatch->commitChanges();
2811 return sal_True;
2813 catch ( lang::WrappedTargetException const & )
2817 OSL_FAIL( "Content::flushData - Error!" );
2818 return sal_False;
2821 //=========================================================================
2822 uno::Reference< io::XInputStream > Content::getInputStream()
2824 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2826 uno::Reference< io::XInputStream > xStream;
2827 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2828 if ( !xNA.is() )
2829 return xStream;
2831 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2832 return xStream;
2836 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2837 uno::Reference< io::XActiveDataSink > xSink;
2838 aEntry >>= xSink;
2840 if ( !xSink.is() )
2842 OSL_FAIL( "Content::getInputStream - "
2843 "Got no XActiveDataSink interface!" );
2844 return xStream;
2847 xStream = xSink->getInputStream();
2849 OSL_ENSURE( xStream.is(),
2850 "Content::getInputStream - Got no stream!" );
2852 catch ( container::NoSuchElementException const & )
2854 // getByHierarchicalName
2857 return xStream;
2860 //=========================================================================
2861 uno::Reference< container::XEnumeration > Content::getIterator()
2863 osl::Guard< osl::Mutex > aGuard( m_aMutex );
2865 uno::Reference< container::XEnumeration > xIter;
2866 uno::Reference< container::XHierarchicalNameAccess > xNA = getPackage();
2867 if ( !xNA.is() )
2868 return xIter;
2870 if ( !xNA->hasByHierarchicalName( m_aUri.getPath() ) )
2871 return xIter;
2875 uno::Any aEntry = xNA->getByHierarchicalName( m_aUri.getPath() );
2876 uno::Reference< container::XEnumerationAccess > xIterFac;
2877 aEntry >>= xIterFac;
2879 if ( !xIterFac.is() )
2881 OSL_FAIL( "Content::getIterator - "
2882 "Got no XEnumerationAccess interface!" );
2883 return xIter;
2886 xIter = xIterFac->createEnumeration();
2888 OSL_ENSURE( xIter.is(),
2889 "Content::getIterator - Got no iterator!" );
2891 catch ( container::NoSuchElementException const & )
2893 // getByHierarchicalName
2896 return xIter;
2899 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */