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