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