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