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