LibreOffice Module ucb (master)  1
bc.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 #include <rtl/uri.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <rtl/ref.hxx>
23 
24 #include <tools/diagnose_ex.h>
25 #include <com/sun/star/lang/NoSupportException.hpp>
26 #include <com/sun/star/sdbc/SQLException.hpp>
27 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
28 #include <com/sun/star/ucb/OpenMode.hpp>
29 #include <com/sun/star/beans/IllegalTypeException.hpp>
30 #include <com/sun/star/io/XActiveDataStreamer.hpp>
31 #include <com/sun/star/io/XOutputStream.hpp>
32 #include <com/sun/star/io/XActiveDataSink.hpp>
33 #include <com/sun/star/ucb/NameClash.hpp>
34 #include <comphelper/fileurl.hxx>
38 #include "filglob.hxx"
39 #include "filid.hxx"
40 #include "filrow.hxx"
41 #include "bc.hxx"
42 #include "prov.hxx"
43 #include "filerror.hxx"
44 #include "filinsreq.hxx"
45 
46 using namespace fileaccess;
47 using namespace com::sun::star;
48 using namespace com::sun::star::uno;
49 using namespace com::sun::star::ucb;
50 
51 #if OSL_DEBUG_LEVEL > 0
52 #define THROW_WHERE SAL_WHERE
53 #else
54 #define THROW_WHERE ""
55 #endif
56 
59 
61  : public PropertyListeners_impl
62 {
63 public:
64  explicit PropertyListeners( ::osl::Mutex& aMutex )
65  : PropertyListeners_impl( aMutex )
66  {
67  }
68 };
69 
70 
71 /****************************************************************************************/
72 /* */
73 /* BaseContent */
74 /* */
75 /****************************************************************************************/
76 
77 
78 // Private Constructor for just inserted Contents
79 
81  const OUString& parentName,
82  bool bFolder )
83  : m_pMyShell( pMyShell ),
84  m_aUncPath( parentName ),
85  m_bFolder( bFolder ),
86  m_nState( JustInserted )
87 {
88  m_pMyShell->m_pProvider->acquire();
89  // No registering, since we have no name
90 }
91 
92 
93 // Constructor for full featured Contents
94 
96  const Reference< XContentIdentifier >& xContentIdentifier,
97  const OUString& aUncPath )
98  : m_pMyShell( pMyShell ),
99  m_xContentIdentifier( xContentIdentifier ),
100  m_aUncPath( aUncPath ),
101  m_bFolder( false ),
102  m_nState( FullFeatured )
103 {
104  m_pMyShell->m_pProvider->acquire();
107 }
108 
109 
111 {
112  if( ( m_nState & FullFeatured ) || ( m_nState & Deleted ) )
113  {
115  }
116  m_pMyShell->m_pProvider->release();
117 }
118 
119 
120 // XComponent
121 
122 
123 void SAL_CALL
125 {
126  osl::MutexGuard aGuard( m_aMutex );
127 
128  if ( ! m_pDisposeEventListeners )
131 
132  m_pDisposeEventListeners->addInterface( Listener );
133 }
134 
135 
136 void SAL_CALL
138 {
139  osl::MutexGuard aGuard( m_aMutex );
140 
142  m_pDisposeEventListeners->removeInterface( Listener );
143 }
144 
145 
146 void SAL_CALL
148 {
149  lang::EventObject aEvt;
150  std::unique_ptr<comphelper::OInterfaceContainerHelper2> pDisposeEventListeners;
151  std::unique_ptr<comphelper::OInterfaceContainerHelper2> pContentEventListeners;
152  std::unique_ptr<comphelper::OInterfaceContainerHelper2> pPropertySetInfoChangeListeners;
153  std::unique_ptr<PropertyListeners> pPropertyListener;
154 
155  {
156  osl::MutexGuard aGuard( m_aMutex );
157  aEvt.Source = static_cast< XContent* >( this );
158 
159  pDisposeEventListeners = std::move(m_pDisposeEventListeners);
160  pContentEventListeners = std::move(m_pContentEventListeners);
161  pPropertySetInfoChangeListeners = std::move(m_pPropertySetInfoChangeListeners);
162  pPropertyListener = std::move(m_pPropertyListener);
163  }
164 
165  if ( pDisposeEventListeners && pDisposeEventListeners->getLength() )
166  pDisposeEventListeners->disposeAndClear( aEvt );
167 
168  if ( pContentEventListeners && pContentEventListeners->getLength() )
169  pContentEventListeners->disposeAndClear( aEvt );
170 
171  if( pPropertyListener )
172  pPropertyListener->disposeAndClear( aEvt );
173 
174  if( pPropertySetInfoChangeListeners )
175  pPropertySetInfoChangeListeners->disposeAndClear( aEvt );
176 }
177 
178 // XServiceInfo
179 OUString SAL_CALL
181 {
182  return "com.sun.star.comp.ucb.FileContent";
183 }
184 
185 sal_Bool SAL_CALL
186 BaseContent::supportsService( const OUString& ServiceName )
187 {
188  return cppu::supportsService( this, ServiceName );
189 }
190 
191 Sequence< OUString > SAL_CALL
193 {
194  Sequence<OUString> ret { "com.sun.star.ucb.FileContent" };
195  return ret;
196 }
197 
198 // XCommandProcessor
199 
200 
201 sal_Int32 SAL_CALL
203 {
204  return m_pMyShell->getCommandId();
205 }
206 
207 
208 void SAL_CALL
209 BaseContent::abort( sal_Int32 /*CommandId*/ )
210 {
211 }
212 
213 
214 Any SAL_CALL
215 BaseContent::execute( const Command& aCommand,
216  sal_Int32 CommandId,
217  const Reference< XCommandEnvironment >& Environment )
218 {
219  if( ! CommandId )
220  // A Command with commandid zero cannot be aborted
221  CommandId = createCommandIdentifier();
222 
223  m_pMyShell->startTask( CommandId,
224  Environment );
225 
226  Any aAny;
227 
228  if (aCommand.Name == "getPropertySetInfo") // No exceptions
229  {
230  aAny <<= getPropertySetInfo();
231  }
232  else if (aCommand.Name == "getCommandInfo") // no exceptions
233  {
234  aAny <<= getCommandInfo();
235  }
236  else if ( aCommand.Name == "setPropertyValues" )
237  {
238  Sequence< beans::PropertyValue > sPropertyValues;
239 
240  if( ! ( aCommand.Argument >>= sPropertyValues ) )
241  m_pMyShell->installError( CommandId,
243  else
244  aAny <<= setPropertyValues( CommandId,sPropertyValues ); // calls endTask by itself
245  }
246  else if ( aCommand.Name == "getPropertyValues" )
247  {
248  Sequence< beans::Property > ListOfRequestedProperties;
249 
250  if( ! ( aCommand.Argument >>= ListOfRequestedProperties ) )
251  m_pMyShell->installError( CommandId,
253  else
254  aAny <<= getPropertyValues( CommandId,
255  ListOfRequestedProperties );
256  }
257  else if ( aCommand.Name == "open" )
258  {
259  OpenCommandArgument2 aOpenArgument;
260  if( ! ( aCommand.Argument >>= aOpenArgument ) )
261  m_pMyShell->installError( CommandId,
263  else
264  {
265  Reference< XDynamicResultSet > result = open( CommandId,aOpenArgument );
266  if( result.is() )
267  aAny <<= result;
268  }
269  }
270  else if ( aCommand.Name == "delete" )
271  {
272  if( ! aCommand.Argument.has< bool >() )
273  m_pMyShell->installError( CommandId,
275  else
276  deleteContent( CommandId );
277  }
278  else if ( aCommand.Name == "transfer" )
279  {
280  TransferInfo aTransferInfo;
281  if( ! ( aCommand.Argument >>= aTransferInfo ) )
282  m_pMyShell->installError( CommandId,
284  else
285  transfer( CommandId, aTransferInfo );
286  }
287  else if ( aCommand.Name == "insert" )
288  {
289  InsertCommandArgument aInsertArgument;
290  if( ! ( aCommand.Argument >>= aInsertArgument ) )
291  m_pMyShell->installError( CommandId,
293  else
294  insert( CommandId,aInsertArgument );
295  }
296  else if ( aCommand.Name == "getCasePreservingURL" )
297  {
298  Reference< sdbc::XRow > xRow = getPropertyValues( CommandId, { { "CasePreservingURL", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
299  OUString CasePreservingURL = xRow->getString(1);
300  if(!xRow->wasNull())
301  aAny <<= CasePreservingURL;
302  }
303  else if ( aCommand.Name == "createNewContent" )
304  {
305  ucb::ContentInfo aArg;
306  if ( !( aCommand.Argument >>= aArg ) )
307  m_pMyShell->installError( CommandId,
309  else
310  aAny <<= createNewContent( aArg );
311  }
312  else
313  m_pMyShell->installError( CommandId,
315 
316 
317  // This is the only function allowed to throw an exception
318  endTask( CommandId );
319 
320  return aAny;
321 }
322 
323 
324 void SAL_CALL
326  const Sequence< OUString >& PropertyNames,
328 {
329  if( ! Listener.is() )
330  return;
331 
332  osl::MutexGuard aGuard( m_aMutex );
333 
334  if( ! m_pPropertyListener )
336 
337 
338  if( !PropertyNames.hasElements() )
339  m_pPropertyListener->addInterface( OUString(),Listener );
340  else
341  {
343  for( const auto& rName : PropertyNames )
344  if( xProp->hasPropertyByName( rName ) )
345  m_pPropertyListener->addInterface( rName,Listener );
346  }
347 }
348 
349 
350 void SAL_CALL
353 {
354  if( ! Listener.is() )
355  return;
356 
357  osl::MutexGuard aGuard( m_aMutex );
358 
359  if( ! m_pPropertyListener )
360  return;
361 
362  for( const auto& rName : PropertyNames )
363  m_pPropertyListener->removeInterface( rName,Listener );
364 
365  m_pPropertyListener->removeInterface( OUString(), Listener );
366 }
367 
368 
369 // XContent
370 
371 
374 {
375  return m_xContentIdentifier;
376 }
377 
378 
379 OUString SAL_CALL
381 {
382  if( !( m_nState & Deleted ) )
383  {
384  if( m_nState & JustInserted )
385  {
386  if ( m_bFolder )
388  else
390  }
391  else
392  {
393  try
394  {
395  // Who am I ?
396  Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
397  bool IsDocument = xRow->getBoolean( 1 );
398 
399  if ( !xRow->wasNull() )
400  {
401  if ( IsDocument )
403  else
405  }
406  else
407  {
408  OSL_FAIL( "BaseContent::getContentType - Property value was null!" );
409  }
410  }
411  catch (const sdbc::SQLException&)
412  {
413  TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
414  }
415  }
416  }
417 
418  return OUString();
419 }
420 
421 
422 void SAL_CALL
424  const Reference< XContentEventListener >& Listener )
425 {
426  osl::MutexGuard aGuard( m_aMutex );
427 
428  if ( ! m_pContentEventListeners )
431 
432 
433  m_pContentEventListeners->addInterface( Listener );
434 }
435 
436 
437 void SAL_CALL
439  const Reference< XContentEventListener >& Listener )
440 {
441  osl::MutexGuard aGuard( m_aMutex );
442 
444  m_pContentEventListeners->removeInterface( Listener );
445 }
446 
447 
448 // XPropertyContainer
449 
450 
451 void SAL_CALL
453  const OUString& Name,
454  sal_Int16 Attributes,
455  const Any& DefaultValue )
456 {
457  if( ( m_nState & JustInserted ) || ( m_nState & Deleted ) || Name.isEmpty() )
458  {
459  throw lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
460  }
461 
462  m_pMyShell->associate( m_aUncPath,Name,DefaultValue,Attributes );
463 }
464 
465 
466 void SAL_CALL
467 BaseContent::removeProperty( const OUString& Name )
468 {
469 
470  if( m_nState & Deleted )
471  throw beans::UnknownPropertyException( Name );
472 
474 }
475 
476 
477 // XContentCreator
478 
479 
482 {
484 }
485 
486 
487 Reference< XContent > SAL_CALL
489 {
490  // Check type.
491  if ( Info.Type.isEmpty() )
492  return Reference< XContent >();
493 
494  bool bFolder = Info.Type == TaskManager::FolderContentType;
495  if ( !bFolder )
496  {
497  if ( Info.Type != TaskManager::FileContentType )
498  {
499  // Neither folder nor file to create!
500  return Reference< XContent >();
501  }
502  }
503 
504  // Who am I ?
505  bool IsDocument = false;
506 
507  try
508  {
509  Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
510  IsDocument = xRow->getBoolean( 1 );
511 
512  if ( xRow->wasNull() )
513  {
514  IsDocument = false;
515 // OSL_FAIL( // "BaseContent::createNewContent - Property value was null!" );
516 // return Reference< XContent >();
517  }
518  }
519  catch (const sdbc::SQLException&)
520  {
521  TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
522  return Reference< XContent >();
523  }
524 
525  OUString dstUncPath;
526 
527  if( IsDocument )
528  {
529  // KSO: Why is a document a XContentCreator? This is quite unusual.
530  dstUncPath = getParentName( m_aUncPath );
531  }
532  else
533  dstUncPath = m_aUncPath;
534 
535  return new BaseContent( m_pMyShell, dstUncPath, bFolder );
536 }
537 
538 
539 // XPropertySetInfoChangeNotifier
540 
541 
542 void SAL_CALL
545 {
546  osl::MutexGuard aGuard( m_aMutex );
549 
550  m_pPropertySetInfoChangeListeners->addInterface( Listener );
551 }
552 
553 
554 void SAL_CALL
557 {
558  osl::MutexGuard aGuard( m_aMutex );
559 
561  m_pPropertySetInfoChangeListeners->removeInterface( Listener );
562 }
563 
564 
565 // XChild
566 
567 
570 {
571  OUString ParentUnq = getParentName( m_aUncPath );
572  OUString ParentUrl;
573 
574 
575  bool err = fileaccess::TaskManager::getUrlFromUnq( ParentUnq, ParentUrl );
576  if( err )
577  return Reference< XInterface >( nullptr );
578 
580 
581  try
582  {
583  return Reference<XInterface>( m_pMyShell->m_pProvider->queryContent( Identifier ), UNO_QUERY );
584  }
585  catch (const IllegalIdentifierException&)
586  {
587  return Reference< XInterface >();
588  }
589 }
590 
591 
592 void SAL_CALL
594  const Reference< XInterface >& )
595 {
596  throw lang::NoSupportException( THROW_WHERE );
597 }
598 
599 
600 // Private Methods
601 
602 
605 {
606  if( m_nState & Deleted )
607  return Reference< XCommandInfo >();
608 
609  return m_pMyShell->info_c();
610 }
611 
612 
615 {
616  if( m_nState & Deleted )
618 
619  return m_pMyShell->info_p( m_aUncPath );
620 }
621 
624  sal_Int32 nMyCommandIdentifier,
625  const Sequence< beans::Property >& PropertySet )
626 {
627  sal_Int32 nProps = PropertySet.getLength();
628  if ( !nProps )
629  return Reference< sdbc::XRow >();
630 
631  if( m_nState & Deleted )
632  {
633  Sequence< Any > aValues( nProps );
634  return Reference< sdbc::XRow >( new XRow_impl( m_pMyShell, aValues ) );
635  }
636 
637  if( m_nState & JustInserted )
638  {
639  Sequence< Any > aValues( nProps );
640  Any* pValues = aValues.getArray();
641 
642  const beans::Property* pProps = PropertySet.getConstArray();
643 
644  for ( sal_Int32 n = 0; n < nProps; ++n )
645  {
646  const beans::Property& rProp = pProps[ n ];
647  Any& rValue = pValues[ n ];
648 
649  if ( rProp.Name == "ContentType" )
650  {
651  rValue <<= (m_bFolder ? OUString(TaskManager::FolderContentType)
652  : OUString(TaskManager::FileContentType));
653  }
654  else if ( rProp.Name == "IsFolder" )
655  {
656  rValue <<= m_bFolder;
657  }
658  else if ( rProp.Name == "IsDocument" )
659  {
660  rValue <<= !m_bFolder;
661  }
662  }
663 
665  new XRow_impl( m_pMyShell, aValues ) );
666  }
667 
668  return m_pMyShell->getv( nMyCommandIdentifier,
669  m_aUncPath,
670  PropertySet );
671 }
672 
673 
676  sal_Int32 nMyCommandIdentifier,
677  const Sequence< beans::PropertyValue >& Values )
678 {
679  if( m_nState & Deleted )
680  { // To do
681  return Sequence< Any >( Values.getLength() );
682  }
683 
684  static const OUStringLiteral Title(u"Title");
685 
686  // Special handling for files which have to be inserted
687  if( m_nState & JustInserted )
688  {
689  for( const auto& rValue : Values )
690  {
691  if( rValue.Name == Title )
692  {
693  OUString NewTitle;
694  if( rValue.Value >>= NewTitle )
695  {
697  {
698  // User wants to set another Title before "insert".
699  // m_aUncPath contains previous own URI.
700 
701  sal_Int32 nLastSlash = m_aUncPath.lastIndexOf( '/' );
702  bool bTrailingSlash = false;
703  if ( nLastSlash == m_aUncPath.getLength() - 1 )
704  {
705  bTrailingSlash = true;
706  nLastSlash
707  = m_aUncPath.lastIndexOf( '/', nLastSlash );
708  }
709 
710  OSL_ENSURE( nLastSlash != -1,
711  "BaseContent::setPropertyValues: "
712  "Invalid URL!" );
713 
714  OUStringBuffer aBuf(
715  m_aUncPath.subView( 0, nLastSlash + 1 ) );
716 
717  if ( !NewTitle.isEmpty() )
718  {
719  aBuf.append( NewTitle );
720  if ( bTrailingSlash )
721  aBuf.append( '/' );
722  }
723  else
724  {
725  m_nState &= ~NameForInsertionSet;
726  }
727 
728  m_aUncPath = aBuf.makeStringAndClear();
729  }
730  else
731  {
732  if ( !NewTitle.isEmpty() )
733  {
734  // Initial Title before "insert".
735  // m_aUncPath contains parent's URI.
736 
737  if( !m_aUncPath.endsWith( "/" ) )
738  m_aUncPath += "/";
739 
740  m_aUncPath += rtl::Uri::encode( NewTitle,
741  rtl_UriCharClassPchar,
742  rtl_UriEncodeIgnoreEscapes,
743  RTL_TEXTENCODING_UTF8 );
745  }
746  }
747  }
748  }
749  }
750 
751  return Sequence< Any >( Values.getLength() );
752  }
753  else
754  {
755  Sequence< Any > ret = m_pMyShell->setv( m_aUncPath, // Does not handle Title
756  Values );
757 
758  // Special handling Title: Setting Title is equivalent to a renaming of the underlying file
759  for( sal_Int32 i = 0; i < Values.getLength(); ++i )
760  {
761  if( Values[i].Name != Title )
762  continue; // handled by setv
763 
764  OUString NewTitle;
765  if( !( Values[i].Value >>= NewTitle ) )
766  {
767  ret[i] <<= beans::IllegalTypeException( THROW_WHERE );
768  break;
769  }
770  else if( NewTitle.isEmpty() )
771  {
772  ret[i] <<= lang::IllegalArgumentException( THROW_WHERE, uno::Reference< uno::XInterface >(), 0 );
773  break;
774  }
775 
776 
777  OUString aDstName = getParentName( m_aUncPath );
778  if( !aDstName.endsWith("/") )
779  aDstName += "/";
780 
781  aDstName += rtl::Uri::encode( NewTitle,
782  rtl_UriCharClassPchar,
783  rtl_UriEncodeIgnoreEscapes,
784  RTL_TEXTENCODING_UTF8 );
785 
786  m_pMyShell->move( nMyCommandIdentifier, // move notifies the children also;
787  m_aUncPath,
788  aDstName,
789  NameClash::KEEP );
790 
791  try
792  {
793  endTask( nMyCommandIdentifier );
794  }
795  catch(const Exception& e)
796  {
797  ret[i] <<= e;
798  }
799 
800  // NameChanges come back through a ContentEvent
801  break; // only handling Title
802  } // end for
803 
804  return ret;
805  }
806 }
807 
808 
811  sal_Int32 nMyCommandIdentifier,
812  const OpenCommandArgument2& aCommandArgument )
813 {
815 
816  if( m_nState & Deleted )
817  {
818  m_pMyShell->installError( nMyCommandIdentifier,
820  }
821  else if( m_nState & JustInserted )
822  {
823  m_pMyShell->installError( nMyCommandIdentifier,
825  }
826  else
827  {
828  if( aCommandArgument.Mode == OpenMode::DOCUMENT ||
829  aCommandArgument.Mode == OpenMode::DOCUMENT_SHARE_DENY_NONE )
830 
831  {
832  Reference< io::XOutputStream > outputStream( aCommandArgument.Sink,UNO_QUERY );
833  if( outputStream.is() )
834  {
835  m_pMyShell->page( nMyCommandIdentifier,
836  m_aUncPath,
837  outputStream );
838  }
839 
840  bool bLock = ( aCommandArgument.Mode != OpenMode::DOCUMENT_SHARE_DENY_NONE );
841 
842  Reference< io::XActiveDataSink > activeDataSink( aCommandArgument.Sink,UNO_QUERY );
843  if( activeDataSink.is() )
844  {
845  activeDataSink->setInputStream( m_pMyShell->open( nMyCommandIdentifier,
846  m_aUncPath,
847  bLock ) );
848  }
849 
850  Reference< io::XActiveDataStreamer > activeDataStreamer( aCommandArgument.Sink,UNO_QUERY );
851  if( activeDataStreamer.is() )
852  {
853  activeDataStreamer->setStream( m_pMyShell->open_rw( nMyCommandIdentifier,
854  m_aUncPath,
855  bLock ) );
856  }
857  }
858  else if ( aCommandArgument.Mode == OpenMode::ALL ||
859  aCommandArgument.Mode == OpenMode::FOLDERS ||
860  aCommandArgument.Mode == OpenMode::DOCUMENTS )
861  {
862  retValue = m_pMyShell->ls( nMyCommandIdentifier,
863  m_aUncPath,
864  aCommandArgument.Mode,
865  aCommandArgument.Properties,
866  aCommandArgument.SortingInfo );
867  }
868 // else if( aCommandArgument.Mode ==
869 // OpenMode::DOCUMENT_SHARE_DENY_NONE ||
870 // aCommandArgument.Mode ==
871 // OpenMode::DOCUMENT_SHARE_DENY_WRITE )
872 // m_pMyShell->installError( nMyCommandIdentifier,
873 // TASKHANDLING_UNSUPPORTED_OPEN_MODE,
874 // aCommandArgument.Mode);
875  else
876  m_pMyShell->installError( nMyCommandIdentifier,
878  aCommandArgument.Mode);
879  }
880 
881  return retValue;
882 }
883 
884 
885 void
886 BaseContent::deleteContent( sal_Int32 nMyCommandIdentifier )
887 {
888  if( m_nState & Deleted )
889  return;
890 
891  if( m_pMyShell->remove( nMyCommandIdentifier,m_aUncPath ) )
892  {
893  osl::MutexGuard aGuard( m_aMutex );
894  m_nState |= Deleted;
895  }
896 }
897 
898 
899 void
900 BaseContent::transfer( sal_Int32 nMyCommandIdentifier,
901  const TransferInfo& aTransferInfo )
902 {
903  if( m_nState & Deleted )
904  return;
905 
906  if( !comphelper::isFileUrl(aTransferInfo.SourceURL) )
907  {
908  m_pMyShell->installError( nMyCommandIdentifier,
910  return;
911  }
912 
913  OUString srcUnc;
914  if( fileaccess::TaskManager::getUnqFromUrl( aTransferInfo.SourceURL,srcUnc ) )
915  {
916  m_pMyShell->installError( nMyCommandIdentifier,
918  return;
919  }
920 
921  OUString srcUncPath = srcUnc;
922 
923  // Determine the new title !
924  OUString NewTitle;
925  if( !aTransferInfo.NewTitle.isEmpty() )
926  NewTitle = rtl::Uri::encode( aTransferInfo.NewTitle,
927  rtl_UriCharClassPchar,
928  rtl_UriEncodeIgnoreEscapes,
929  RTL_TEXTENCODING_UTF8 );
930  else
931  NewTitle = srcUncPath.copy( 1 + srcUncPath.lastIndexOf( '/' ) );
932 
933  // Is destination a document or a folder ?
934  Reference< sdbc::XRow > xRow = getPropertyValues( nMyCommandIdentifier,{ { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } } );
935  bool IsDocument = xRow->getBoolean( 1 );
936  if( xRow->wasNull() )
937  { // Destination file type could not be determined
938  m_pMyShell->installError( nMyCommandIdentifier,
940  return;
941  }
942 
943  OUString dstUncPath;
944  if( IsDocument )
945  { // as sibling
946  sal_Int32 lastSlash = m_aUncPath.lastIndexOf( '/' );
947  dstUncPath = m_aUncPath.copy(0,lastSlash );
948  }
949  else
950  // as child
951  dstUncPath = m_aUncPath;
952 
953  dstUncPath += "/" + NewTitle;
954 
955  sal_Int32 NameClash = aTransferInfo.NameClash;
956 
957  if( aTransferInfo.MoveData )
958  m_pMyShell->move( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
959  else
960  m_pMyShell->copy( nMyCommandIdentifier,srcUncPath,dstUncPath,NameClash );
961 }
962 
963 
964 void BaseContent::insert( sal_Int32 nMyCommandIdentifier,
965  const InsertCommandArgument& aInsertArgument )
966 {
967  if( m_nState & FullFeatured )
968  {
969  m_pMyShell->write( nMyCommandIdentifier,
970  m_aUncPath,
971  aInsertArgument.ReplaceExisting,
972  aInsertArgument.Data );
973  return;
974  }
975 
976  if( ! ( m_nState & JustInserted ) )
977  {
978  m_pMyShell->installError( nMyCommandIdentifier,
980  return;
981  }
982 
983  // Inserts the content, which has the flag m_bIsFresh
984 
985  if( ! (m_nState & NameForInsertionSet) )
986  {
987  m_pMyShell->installError( nMyCommandIdentifier,
989  return;
990  }
991 
992  // Inserting a document or a file?
993  bool bDocument = false;
994 
995  Reference< sdbc::XRow > xRow = getPropertyValues( -1, { { "IsDocument", -1, cppu::UnoType<sal_Bool>::get(), 0 } });
996 
997  bool contentTypeSet = true; // is set to false, if contentType not set
998  try
999  {
1000  bDocument = xRow->getBoolean( 1 );
1001  if( xRow->wasNull() )
1002  contentTypeSet = false;
1003 
1004  }
1005  catch (const sdbc::SQLException&)
1006  {
1007  TOOLS_WARN_EXCEPTION("ucb.ucp.file", "");
1008  contentTypeSet = false;
1009  }
1010 
1011  if( ! contentTypeSet )
1012  {
1013  m_pMyShell->installError( nMyCommandIdentifier,
1015  return;
1016  }
1017 
1018 
1019  bool success = false;
1020  if( bDocument )
1021  success = m_pMyShell->mkfil( nMyCommandIdentifier,
1022  m_aUncPath,
1023  aInsertArgument.ReplaceExisting,
1024  aInsertArgument.Data );
1025  else
1026  {
1027  while( ! success )
1028  {
1029  success = m_pMyShell->mkdir( nMyCommandIdentifier,
1030  m_aUncPath,
1031  aInsertArgument.ReplaceExisting );
1032  if( success )
1033  break;
1034 
1035  XInteractionRequestImpl aRequestImpl(
1036  rtl::Uri::decode(
1038  rtl_UriDecodeWithCharset,
1039  RTL_TEXTENCODING_UTF8),
1040  static_cast<cppu::OWeakObject*>(this),
1041  m_pMyShell,nMyCommandIdentifier);
1042  uno::Reference<task::XInteractionRequest> const& xReq(aRequestImpl.getRequest());
1043 
1044  m_pMyShell->handleTask( nMyCommandIdentifier, xReq );
1045  if (aRequestImpl.aborted() || aRequestImpl.newName().isEmpty())
1046  // means aborting
1047  break;
1048 
1049  // determine new uncpath
1050  m_pMyShell->clearError( nMyCommandIdentifier );
1052  if( !m_aUncPath.endsWith( "/" ) )
1053  m_aUncPath += "/";
1054 
1055  m_aUncPath += rtl::Uri::encode( aRequestImpl.newName(),
1056  rtl_UriCharClassPchar,
1057  rtl_UriEncodeIgnoreEscapes,
1058  RTL_TEXTENCODING_UTF8 );
1059  }
1060  }
1061 
1062  if ( ! success )
1063  return;
1064 
1066 
1069 
1070  osl::MutexGuard aGuard( m_aMutex );
1072 }
1073 
1074 
1075 void BaseContent::endTask( sal_Int32 CommandId )
1076 {
1077  // This is the only function allowed to throw an exception
1078  m_pMyShell->endTask( CommandId,m_aUncPath,this );
1079 }
1080 
1081 
1082 std::optional<ContentEventNotifier>
1084 {
1085  osl::MutexGuard aGuard( m_aMutex );
1086 
1087  m_nState |= Deleted;
1088 
1090  return {};
1091 
1093  this,
1095  m_pContentEventListeners->getElements() );
1096 }
1097 
1098 
1099 std::optional<ContentEventNotifier>
1100 BaseContent::cEXC( const OUString& aNewName )
1101 {
1102  osl::MutexGuard aGuard( m_aMutex );
1103 
1105  m_aUncPath = aNewName;
1106  m_xContentIdentifier = new FileContentIdentifier( aNewName );
1107 
1109  return {};
1111  this,
1113  xOldRef,
1114  m_pContentEventListeners->getElements() );
1115 }
1116 
1117 
1118 std::optional<ContentEventNotifier>
1120 {
1121  osl::MutexGuard aGuard( m_aMutex );
1123  return {};
1125  this,
1127  m_pContentEventListeners->getElements() );
1128 }
1129 
1130 std::optional<PropertySetInfoChangeNotifier>
1132 {
1133  osl::MutexGuard aGuard( m_aMutex );
1135  return {};
1137 }
1138 
1139 
1140 std::optional<PropertyChangeNotifier>
1142 {
1143  osl::MutexGuard aGuard( m_aMutex );
1144 
1145  if (!m_pPropertyListener)
1146  return {};
1147 
1148  const std::vector< OUString > seqNames = m_pPropertyListener->getContainedTypes();
1149  if( seqNames.empty() )
1150  return {};
1151 
1152  ListenerMap listener;
1153  for( const auto& rName : seqNames )
1154  {
1155  comphelper::OInterfaceContainerHelper2* pContainer = m_pPropertyListener->getContainer(rName);
1156  if (!pContainer)
1157  continue;
1158  listener[rName] = pContainer->getElements();
1159  }
1160 
1161  return PropertyChangeNotifier( this, std::move(listener) );
1162 }
1163 
1164 
1165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT
Definition: filerror.hxx:29
#define TASKHANDLING_WRONG_TRANSFER_ARGUMENT
Definition: filerror.hxx:32
css::uno::Reference< css::ucb::XCommandInfo > getCommandInfo()
Definition: bc.cxx:604
constexpr OUStringLiteral IsDocument(u"IsDocument")
#define TASKHANDLING_WRONG_DELETE_ARGUMENT
Definition: filerror.hxx:31
css::uno::Reference< css::ucb::XContentIdentifier > m_xContentIdentifier
Definition: bc.hxx:196
#define TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT
Definition: filerror.hxx:28
virtual void SAL_CALL setParent(const css::uno::Reference< css::uno::XInterface > &Parent) override
Definition: bc.cxx:593
void endTask(sal_Int32 CommandId, const OUString &aUnqPath, BaseContent *pContent)
Deinstalls the task and evaluates a possibly set error code.
Definition: filtask.cxx:383
std::optional< ContentEventNotifier > cCEL() override
Definition: bc.cxx:1119
void deleteContent(sal_Int32 nMyCommandIdentifier)
Definition: bc.cxx:886
#define TASKHANDLING_UNSUPPORTED_OPEN_MODE
Definition: filerror.hxx:35
friend class ContentEventNotifier
Definition: bc.hxx:254
virtual void SAL_CALL abort(sal_Int32 CommandId) override
Definition: bc.cxx:209
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
Definition: bc.cxx:186
comphelper::OMultiTypeInterfaceContainerHelperVar2< OUString > PropertyListeners_impl
Definition: bc.cxx:58
virtual css::uno::Any SAL_CALL execute(const css::ucb::Command &aCommand, sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &Environment) override
Definition: bc.cxx:215
sal_Int64 n
aBuf
css::uno::Reference< css::ucb::XDynamicResultSet > open(sal_Int32 nMyCommandIdentifier, const css::ucb::OpenCommandArgument2 &aCommandArgument)
Definition: bc.cxx:810
std::unique_ptr< comphelper::OInterfaceContainerHelper2 > m_pPropertySetInfoChangeListeners
Definition: bc.hxx:211
void deassociate(const OUString &UnqPath, const OUString &PropertyName)
Definition: filtask.cxx:569
virtual void SAL_CALL addContentEventListener(const css::uno::Reference< css::ucb::XContentEventListener > &Listener) override
Definition: bc.cxx:423
OUString Name
bool remove(sal_Int32 CommandId, const OUString &aUnqPath, FileUrlType eTypeToMove=FileUrlType::Unknown, bool MustExist=true)
Deletes the content belonging to fileURL aUnqPath( recursively in case of directory ) ...
Definition: filtask.cxx:1510
void insertDefaultProperties(const OUString &aUnqPath)
Definition: filtask.cxx:1922
virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence< OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override
Definition: bc.cxx:325
Title
#define TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND
Definition: filerror.hxx:38
#define TASKHANDLING_TRANSFER_INVALIDURL
Definition: filerror.hxx:81
virtual void SAL_CALL addProperty(const OUString &Name, sal_Int16 Attributes, const css::uno::Any &DefaultValue) override
Definition: bc.cxx:452
static constexpr OUStringLiteral FolderContentType
Definition: filtask.hxx:630
#define TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND
Definition: filerror.hxx:37
#define TASKHANDLER_UNSUPPORTED_COMMAND
Definition: filerror.hxx:27
virtual void SAL_CALL dispose() override
Definition: bc.cxx:147
virtual void SAL_CALL removeEventListener(const css::uno::Reference< css::lang::XEventListener > &aListener) override
Definition: bc.cxx:137
Value
void installError(sal_Int32 CommandId, sal_Int32 ErrorCode, sal_Int32 minorCode=TASKHANDLER_NO_ERROR)
The error code may be one of the error codes defined in filerror.hxx.
Definition: filtask.cxx:437
virtual sal_Int32 SAL_CALL createCommandIdentifier() override
Definition: bc.cxx:202
FileProvider * m_pProvider
Definition: filtask.hxx:483
std::unique_ptr< PropertyListeners > m_pPropertyListener
Definition: bc.hxx:212
virtual void SAL_CALL addEventListener(const css::uno::Reference< css::lang::XEventListener > &xListener) override
Definition: bc.cxx:124
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
#define TASKHANDLING_TRANSFER_DESTFILETYPE
Definition: filerror.hxx:82
std::unordered_map< OUString, std::vector< css::uno::Reference< css::uno::XInterface > > > ListenerMap
Definition: filnot.hxx:81
PropertyListeners(::osl::Mutex &aMutex)
Definition: bc.cxx:64
virtual void SAL_CALL addPropertySetInfoChangeListener(const css::uno::Reference< css::beans::XPropertySetInfoChangeListener > &Listener) override
Definition: bc.cxx:543
virtual OUString SAL_CALL getContentType() override
Definition: bc.cxx:380
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL createNewContent(const css::ucb::ContentInfo &Info) override
Definition: bc.cxx:488
void transfer(sal_Int32 nMyCommandIdentifier, const css::ucb::TransferInfo &aTransferInfo)
Definition: bc.cxx:900
static bool getUrlFromUnq(const OUString &Unq, OUString &Url)
Definition: filtask.cxx:1973
static constexpr OUStringLiteral FileContentType
Definition: filtask.hxx:632
bool mkfil(sal_Int32 CommandId, const OUString &aFileName, bool OverWrite, const css::uno::Reference< css::io::XInputStream > &aInputStream)
Creates new file with given URL.
Definition: filtask.cxx:1732
std::unique_ptr< comphelper::OInterfaceContainerHelper2 > m_pDisposeEventListeners
Definition: bc.hxx:209
#define TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND
Definition: filerror.hxx:52
err
#define TASKHANDLING_TRANSFER_INVALIDSCHEME
Definition: filerror.hxx:80
#define TOOLS_WARN_EXCEPTION(area, stream)
int i
virtual OUString SAL_CALL getImplementationName() override
Definition: bc.cxx:180
#define TASKHANDLING_WRONG_CREATENEWCONTENT_ARGUMENT
Definition: filerror.hxx:34
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: bc.cxx:192
std::optional< PropertyChangeNotifier > cPCL() override
Definition: bc.cxx:1141
osl::Mutex m_aEventListenerMutex
Definition: bc.hxx:208
void copy(sal_Int32 CommandId, const OUString &srcUnqPath, const OUString &dstUnqPath, sal_Int32 NameClash)
Copies the content belonging to fileURL srcUnqPath to fileURL dstUnqPath ( files and directories ) ...
Definition: filtask.cxx:1338
css::uno::Reference< css::task::XInteractionRequest > const & getRequest() const
Definition: filinsreq.hxx:124
uno::Reference< sdbc::XRow > xRow
float u
unsigned char sal_Bool
sal_uInt16 m_nState
Definition: bc.hxx:204
OUString getTitle(const OUString &aPath)
Definition: filglob.cxx:185
static css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
Definition: filtask.cxx:2902
OUString m_aUncPath
Definition: bc.hxx:197
virtual css::uno::Reference< css::ucb::XContent > SAL_CALL queryContent(const css::uno::Reference< css::ucb::XContentIdentifier > &Identifier) override
Definition: prov.cxx:113
css::uno::Type const & get()
virtual void SAL_CALL removePropertySetInfoChangeListener(const css::uno::Reference< css::beans::XPropertySetInfoChangeListener > &Listener) override
Definition: bc.cxx:555
std::vector< css::uno::Reference< css::uno::XInterface > > getElements() const
void insert(sal_Int32 nMyCommandIdentifier, const css::ucb::InsertCommandArgument &aInsertArgument)
Definition: bc.cxx:964
sal_Int32 getCommandId()
Definition: filtask.cxx:449
void deregisterNotifier(const OUString &aUnqPath, Notifier *pNotifier)
Definition: filtask.cxx:503
constexpr OUStringLiteral CasePreservingURL(u"CasePreservingURL")
css::uno::Reference< css::io::XStream > open_rw(sal_Int32 CommandId, const OUString &aUnqPath, bool bLock)
Given a file URL aUnqPath, this methods returns a XStream which can be used to read and write from/to...
Definition: filtask.cxx:743
virtual void SAL_CALL removeContentEventListener(const css::uno::Reference< css::ucb::XContentEventListener > &Listener) override
Definition: bc.cxx:438
virtual ~BaseContent() override
Definition: bc.cxx:110
css::uno::Reference< css::sdbc::XRow > getv(sal_Int32 CommandId, const OUString &aUnqPath, const css::uno::Sequence< css::beans::Property > &properties)
Reads the values of the properties belonging to fileURL aUnqPath; Returns an XRow object containing t...
const PropertyValue * pValues
virtual css::uno::Reference< css::uno::XInterface > SAL_CALL getParent() override
Definition: bc.cxx:569
css::uno::Sequence< css::uno::Any > setPropertyValues(sal_Int32 nMyCommandIdentifier, const css::uno::Sequence< css::beans::PropertyValue > &Values)
Definition: bc.cxx:675
css::uno::Reference< css::ucb::XCommandInfo > info_c()
Info methods.
Definition: filtask.cxx:805
css::uno::Reference< css::io::XInputStream > open(sal_Int32 CommandId, const OUString &aUnqPath, bool bLock)
Given a file URL aUnqPath, this methods returns a XInputStream which reads from the open file...
Definition: filtask.cxx:711
virtual css::uno::Sequence< css::ucb::ContentInfo > SAL_CALL queryCreatableContentsInfo() override
Definition: bc.cxx:481
#define TASKHANDLING_WRONG_OPEN_ARGUMENT
Definition: filerror.hxx:30
std::unique_ptr< comphelper::OInterfaceContainerHelper2 > m_pContentEventListeners
Definition: bc.hxx:210
static bool getUnqFromUrl(const OUString &Url, OUString &Unq)
Definition: filtask.cxx:1952
COMPHELPER_DLLPUBLIC bool isFileUrl(OUString const &url)
virtual void SAL_CALL removeProperty(const OUString &Name) override
Definition: bc.cxx:467
css::uno::Reference< css::ucb::XDynamicResultSet > ls(sal_Int32 CommandId, const OUString &aUnqPath, const sal_Int32 OpenMode, const css::uno::Sequence< css::beans::Property > &sProperty, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &sSortingInfo)
This method returns the result set containing the children of the directory belonging to file URL aUn...
Definition: filtask.cxx:774
std::optional< ContentEventNotifier > cEXC(const OUString &aNewName) override
Definition: bc.cxx:1100
void move(sal_Int32 CommandId, const OUString &srcUnqPath, const OUString &dstUnqPath, const sal_Int32 NameClash)
Moves the content belonging to fileURL srcUnqPath to fileURL dstUnqPath( files and directories ) ...
Definition: filtask.cxx:1130
void page(sal_Int32 CommandId, const OUString &aUnqPath, const css::uno::Reference< css::io::XOutputStream > &xOutputStream)
Given an xOutputStream, this method writes the content of the file belonging to URL aUnqPath into the...
Definition: filtask.cxx:622
virtual css::uno::Reference< css::ucb::XContentIdentifier > SAL_CALL getIdentifier() override
Definition: bc.cxx:373
css::uno::Sequence< css::uno::Any > setv(const OUString &aUnqPath, const css::uno::Sequence< css::beans::PropertyValue > &values)
Sets the values of the properties belonging to fileURL aUnqPath.
Definition: filtask.cxx:836
Any result
osl::Mutex m_aMutex
Definition: bc.hxx:206
#define THROW_WHERE
Definition: bc.cxx:52
css::uno::Reference< css::beans::XPropertySetInfo > info_p(const OUString &aUnqPath)
Definition: filtask.cxx:819
bool write(sal_Int32 CommandId, const OUString &aUnqPath, bool OverWrite, const css::uno::Reference< css::io::XInputStream > &aInputStream)
writes to the file with given URL.
Definition: filtask.cxx:1763
BaseContent(TaskManager *pMyShell, const OUString &parentName, bool bFolder)
Definition: bc.cxx:80
void endTask(sal_Int32 CommandId)
Definition: bc.cxx:1075
std::optional< PropertySetInfoChangeNotifier > cPSL() override
Definition: bc.cxx:1131
std::optional< ContentEventNotifier > cDEL() override
Definition: bc.cxx:1083
#define TASKHANDLING_WRONG_INSERT_ARGUMENT
Definition: filerror.hxx:33
css::uno::Reference< css::beans::XPropertySetInfo > getPropertySetInfo()
Definition: bc.cxx:614
OUString getParentName(const OUString &aFileName)
Definition: filglob.cxx:192
bool mkdir(sal_Int32 CommandId, const OUString &aDirectoryName, bool OverWrite)
Creates new directory with given URL, recursively if necessary Return:: success of operation...
Definition: filtask.cxx:1672
#define TASKHANDLING_NONAMESET_INSERT_COMMAND
Definition: filerror.hxx:51
void registerNotifier(const OUString &aUnqPath, Notifier *pNotifier)
This two methods register and deregister a change listener for the content belonging to URL aUnqPath...
Definition: filtask.cxx:484
#define TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND
Definition: filerror.hxx:50
void startTask(sal_Int32 CommandId, const css::uno::Reference< css::ucb::XCommandEnvironment > &xCommandEnv)
Definition: filtask.cxx:368
css::uno::Reference< css::sdbc::XRow > getPropertyValues(sal_Int32 nMyCommandIdentifier, const css::uno::Sequence< css::beans::Property > &PropertySet)
Definition: bc.cxx:623
virtual void SAL_CALL removePropertiesChangeListener(const css::uno::Sequence< OUString > &PropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &Listener) override
Definition: bc.cxx:351
void clearError(sal_Int32)
Clears any error which are set on the commandid.
Definition: filtask.cxx:414
void handleTask(sal_Int32 CommandId, const css::uno::Reference< css::task::XInteractionRequest > &request)
Handles an interactionrequest.
Definition: filtask.cxx:456
void associate(const OUString &UnqPath, const OUString &PropertyName, const css::uno::Any &DefaultValue, const sal_Int16 Attributes)
Used to associate and deassociate a new property with the content belonging to URL UnqPath...
Definition: filtask.cxx:530
TaskManager * m_pMyShell
Definition: bc.hxx:195