LibreOffice Module ucbhelper (master) 1
content.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 <sal/config.h>
21
22#include <cassert>
23
24#include <o3tl/unreachable.hxx>
25#include <osl/diagnose.h>
26#include <mutex>
27#include <sal/log.hxx>
29#include <cppuhelper/weak.hxx>
31
33#include <com/sun/star/ucb/CheckinArgument.hpp>
34#include <com/sun/star/ucb/ContentCreationError.hpp>
35#include <com/sun/star/ucb/ContentCreationException.hpp>
36#include <com/sun/star/ucb/IllegalIdentifierException.hpp>
37#include <com/sun/star/ucb/XCommandInfo.hpp>
38#include <com/sun/star/ucb/XCommandProcessor.hpp>
39#include <com/sun/star/ucb/Command.hpp>
40#include <com/sun/star/ucb/ContentAction.hpp>
41#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
42#include <com/sun/star/ucb/InsertCommandArgument.hpp>
43#include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
44#include <com/sun/star/ucb/OpenMode.hpp>
45#include <com/sun/star/ucb/XContentCreator.hpp>
46#include <com/sun/star/ucb/XContentEventListener.hpp>
47#include <com/sun/star/ucb/XDynamicResultSet.hpp>
48#include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
49#include <com/sun/star/ucb/UniversalContentBroker.hpp>
50#include <com/sun/star/ucb/XUniversalContentBroker.hpp>
51#include <com/sun/star/beans/XPropertySetInfo.hpp>
52#include <com/sun/star/beans/Property.hpp>
53#include <com/sun/star/beans/PropertyValue.hpp>
54#include <com/sun/star/sdbc/XRow.hpp>
55#include <com/sun/star/lang/IllegalArgumentException.hpp>
56#include <com/sun/star/beans/UnknownPropertyException.hpp>
57#include <ucbhelper/content.hxx>
61
62namespace com::sun::star::ucb { class XCommandEnvironment; }
63namespace com::sun::star::ucb { class XContentProvider; }
64namespace com::sun::star::sdbc { class XResultSet; }
65
66using namespace com::sun::star::container;
67using namespace com::sun::star::beans;
68using namespace com::sun::star::io;
69using namespace com::sun::star::lang;
70using namespace com::sun::star::sdbc;
71using namespace com::sun::star::task;
72using namespace com::sun::star::ucb;
73using namespace com::sun::star::uno;
74
75namespace ucbhelper
76{
77
78namespace {
79
80class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
81{
82public:
83 virtual sal_Int32 SAL_CALL readBytes(
84 Sequence< sal_Int8 > & data, sal_Int32 nBytesToRead ) override;
85 virtual sal_Int32 SAL_CALL readSomeBytes(
86 Sequence< sal_Int8 > & data, sal_Int32 nMaxBytesToRead ) override;
87 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
88 virtual sal_Int32 SAL_CALL available() override;
89 virtual void SAL_CALL closeInput() override;
90};
91
92}
93
94sal_Int32 EmptyInputStream::readBytes(
95 Sequence< sal_Int8 > & data, sal_Int32 )
96{
97 data.realloc( 0 );
98 return 0;
99}
100
101sal_Int32 EmptyInputStream::readSomeBytes(
102 Sequence< sal_Int8 > & data, sal_Int32 )
103{
104 data.realloc( 0 );
105 return 0;
106}
107
108void EmptyInputStream::skipBytes( sal_Int32 )
109{
110}
111
112sal_Int32 EmptyInputStream::available()
113{
114 return 0;
115}
116
117void EmptyInputStream::closeInput()
118{
119}
120
121
122
123namespace {
124
125class ContentEventListener_Impl : public cppu::OWeakObject,
126 public XContentEventListener
127{
128 Content_Impl& m_rContent;
129
130public:
131 explicit ContentEventListener_Impl( Content_Impl& rContent )
132 : m_rContent( rContent ) {}
133
134 // XInterface
135 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
136 virtual void SAL_CALL acquire()
137 noexcept override;
138 virtual void SAL_CALL release()
139 noexcept override;
140
141 // XContentEventListener
142 virtual void SAL_CALL contentEvent( const ContentEvent& evt ) override;
143
144 // XEventListener ( base of XContentEventListener )
145 virtual void SAL_CALL disposing( const EventObject& Source ) override;
146};
147
148}
149
150
151
152class Content_Impl : public salhelper::SimpleReferenceObject
153{
155
156 mutable OUString m_aURL;
162 mutable std::mutex m_aMutex;
163
164private:
165 void reinit( const Reference< XContent >& xContent );
166 void disposing(const EventObject& Source);
167 const Reference< XContent > & getContent_NoLock();
168 const OUString& getURL_NoLock() const;
169
170public:
173 const Reference< XContent >& rContent,
175
176 virtual ~Content_Impl() override;
177
178 const OUString& getURL() const;
179 Reference< XContent > getContent();
180 Reference< XCommandProcessor > getCommandProcessor();
182 { assert(m_xCtx.is()); return m_xCtx; }
183
184 Any executeCommand( const Command& rCommand );
185
187 inline void setEnvironment(
188 const Reference< XCommandEnvironment >& xNewEnv );
189
190 void inserted();
191};
192
193
194// Helpers.
195
199 const OUString & rURL )
200{
202 = rBroker->queryContentProvider( rURL );
203 if ( !xProv.is() )
204 {
205 throw ContentCreationException(
206 "No Content Provider available for URL: " + rURL,
208 ContentCreationError_NO_CONTENT_PROVIDER );
209 }
210}
211
216 const OUString & rURL)
217{
219 = rBroker->createContentIdentifier( rURL );
220
221 if (!xId.is())
222 {
223 ensureContentProviderForURL( rBroker, rURL );
224
225 throw ContentCreationException(
226 "Unable to create Content Identifier!",
228 ContentCreationError_IDENTIFIER_CREATION_FAILED );
229 }
230
231 return xId;
232}
233
237 const OUString & rURL)
238{
239 return rBroker->createContentIdentifier(rURL);
240}
241
247{
248 Reference< XContent > xContent;
249 OUString msg;
250 try
251 {
252 xContent = rBroker->queryContent( xId );
253 }
254 catch ( IllegalIdentifierException const & e )
255 {
256 msg = e.Message;
257 // handled below.
258 }
259
260 if ( !xContent.is() )
261 {
262 ensureContentProviderForURL( rBroker, xId->getContentIdentifier() );
263
264 throw ContentCreationException(
265 "Unable to create Content for <" + xId->getContentIdentifier() + ">: " + msg,
267 ContentCreationError_CONTENT_CREATION_FAILED );
268 }
269
270 return xContent;
271}
272
277{
278 Reference< XContent > xContent;
279 try
280 {
281 xContent = rBroker->queryContent( xId );
282 }
283 catch ( IllegalIdentifierException const & e )
284 {
285 SAL_WARN("ucbhelper", "getContentNoThrow: " << e);
286 }
287
288 return xContent;
289}
290
291
292// Content Implementation.
293
294
296: m_xImpl( new Content_Impl )
297{
298}
299
300
301Content::Content( const OUString& rURL,
304{
306 UniversalContentBroker::create( rCtx ) );
307
309 = getContentIdentifierThrow(pBroker, rURL);
310
311 Reference< XContent > xContent = getContentThrow(pBroker, xId);
312
313 m_xImpl = new Content_Impl( rCtx, xContent, rEnv );
314}
315
316
320{
321 m_xImpl = new Content_Impl( rCtx, rContent, rEnv );
322}
323
324
325Content::Content( const Content& rOther )
326{
327 m_xImpl = rOther.m_xImpl;
328}
329
330Content::Content( Content&& rOther ) noexcept
331{
332 m_xImpl = std::move(rOther.m_xImpl);
333}
334
335// static
336bool Content::create( const OUString& rURL,
339 Content& rContent )
340{
342 UniversalContentBroker::create( rCtx ) );
343
345 = getContentIdentifierNoThrow(pBroker, rURL);
346 if ( !xId.is() )
347 return false;
348
349 Reference< XContent > xContent = getContentNoThrow(pBroker, xId);
350 if ( !xContent.is() )
351 return false;
352
353 rContent.m_xImpl
354 = new Content_Impl( rCtx, xContent, rEnv );
355
356 return true;
357}
358
359
361{
362}
363
364
366{
367 m_xImpl = rOther.m_xImpl;
368 return *this;
369}
370
371Content& Content::operator=( Content&& rOther ) noexcept
372{
373 m_xImpl = std::move(rOther.m_xImpl);
374 return *this;
375}
376
378{
379 return m_xImpl->getContent();
380}
381
382
383const OUString& Content::getURL() const
384{
385 return m_xImpl->getURL();
386}
387
388
390{
391 return m_xImpl->getEnvironment();
392}
393
394
396 const Reference< XCommandEnvironment >& xNewEnv )
397{
398 m_xImpl->setEnvironment( xNewEnv );
399}
400
401
403{
405 aCommand.Name = "getCommandInfo";
406 aCommand.Handle = -1; // n/a
407 aCommand.Argument = Any();
408
409 Any aResult = m_xImpl->executeCommand( aCommand );
410
412 aResult >>= xInfo;
413 return xInfo;
414}
415
416
418{
419 static constexpr OUStringLiteral sgetPropertySetInfo = u"getPropertySetInfo";
421 aCommand.Name = sgetPropertySetInfo;
422 aCommand.Handle = -1; // n/a
423 aCommand.Argument = Any();
424
425 Any aResult = m_xImpl->executeCommand( aCommand );
426
428 aResult >>= xInfo;
429 return xInfo;
430}
431
432
433Any Content::getPropertyValue( const OUString& rPropertyName )
434{
435 Sequence<OUString> aNames { rPropertyName };
436
437 Sequence< Any > aRet = getPropertyValues( aNames );
438 return aRet.getConstArray()[ 0 ];
439}
440
441
442Any Content::setPropertyValue( const OUString& rName,
443 const Any& rValue )
444{
445 Sequence<OUString> aNames { rName };
446
447 Sequence< Any > aValues( 1 );
448 aValues.getArray()[ 0 ] = rValue;
449
450 Sequence< Any > aErrors = setPropertyValues( aNames, aValues );
451 return aErrors.getConstArray()[ 0 ];
452}
453
454
456 const Sequence< OUString >& rPropertyNames )
457{
458 Reference< XRow > xRow = getPropertyValuesInterface( rPropertyNames );
459
460 sal_Int32 nCount = rPropertyNames.getLength();
461 Sequence< Any > aValues( nCount );
462
463 if ( xRow.is() )
464 {
465 Any* pValues = aValues.getArray();
466
467 for ( sal_Int32 n = 0; n < nCount; ++n )
468 pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
469 }
470
471 return aValues;
472}
473
474
476 const Sequence< OUString >& rPropertyNames )
477{
478 sal_Int32 nCount = rPropertyNames.getLength();
480 Property* pProps = aProps.getArray();
481
482 const OUString* pNames = rPropertyNames.getConstArray();
483
484 for ( sal_Int32 n = 0; n< nCount; ++n )
485 {
486 Property& rProp = pProps[ n ];
487
488 rProp.Name = pNames[ n ];
489 rProp.Handle = -1; // n/a
490// rProp.Type =
491// rProp.Attributes = ;
492 }
493
494 static constexpr OUStringLiteral sgetPropertyValues = u"getPropertyValues";
496 aCommand.Name = sgetPropertyValues;
497 aCommand.Handle = -1; // n/a
498 aCommand.Argument <<= aProps;
499
500 Any aResult = m_xImpl->executeCommand( aCommand );
501
503 aResult >>= xRow;
504 return xRow;
505}
506
507
509 const Sequence< OUString >& rPropertyNames,
510 const Sequence< Any >& rValues )
511{
512 if ( rPropertyNames.getLength() != rValues.getLength() )
513 {
515 Any( IllegalArgumentException(
516 "Length of property names sequence and value "
517 "sequence are unequal!",
518 get(),
519 -1 ) ),
520 m_xImpl->getEnvironment() );
521 // Unreachable
522 }
523
524 sal_Int32 nCount = rValues.getLength();
525 Sequence< PropertyValue > aProps( nCount );
526 PropertyValue* pProps = aProps.getArray();
527
528 const OUString* pNames = rPropertyNames.getConstArray();
529 const Any* pValues = rValues.getConstArray();
530
531 for ( sal_Int32 n = 0; n< nCount; ++n )
532 {
533 PropertyValue& rProp = pProps[ n ];
534
535 rProp.Name = pNames[ n ];
536 rProp.Handle = -1; // n/a
537 rProp.Value = pValues[ n ];
538// rProp.State = ;
539 }
540
542 aCommand.Name = "setPropertyValues";
543 aCommand.Handle = -1; // n/a
544 aCommand.Argument <<= aProps;
545
546 Any aResult = m_xImpl->executeCommand( aCommand );
547
548 Sequence< Any > aErrors;
549 aResult >>= aErrors;
550 return aErrors;
551}
552
553
554Any Content::executeCommand( const OUString& rCommandName,
555 const Any& rCommandArgument )
556{
558 aCommand.Name = rCommandName;
559 aCommand.Handle = -1; // n/a
560 aCommand.Argument = rCommandArgument;
561
562 return m_xImpl->executeCommand( aCommand );
563}
564
565
567 ResultSetInclude eMode )
568{
569 sal_Int32 nCount = rPropertyNames.getLength();
571 Property* pProps = aProps.getArray();
572 const OUString* pNames = rPropertyNames.getConstArray();
573 for ( sal_Int32 n = 0; n < nCount; ++n )
574 {
575 Property& rProp = pProps[ n ];
576 rProp.Name = pNames[ n ];
577 rProp.Handle = -1; // n/a
578 }
579
580 OpenCommandArgument2 aArg;
581 aArg.Mode = ( eMode == INCLUDE_FOLDERS_ONLY )
582 ? OpenMode::FOLDERS
584 ? OpenMode::DOCUMENTS : OpenMode::ALL;
585 aArg.Priority = 0; // unused
586 aArg.Sink.clear(); // unused
587 aArg.Properties = aProps;
588
590 aCommand.Name = "open";
591 aCommand.Handle = -1; // n/a
592 aCommand.Argument <<= aArg;
593
594 return m_xImpl->executeCommand( aCommand );
595}
596
597
599 const Sequence< OUString >& rPropertyNames,
600 ResultSetInclude eMode )
601{
602 Any aCursorAny = createCursorAny( rPropertyNames, eMode );
603
606
607 aCursorAny >>= xDynSet;
608 if ( xDynSet.is() )
609 aResult = xDynSet->getStaticResultSet();
610
611 OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
612
613 if ( !aResult.is() )
614 {
615 // Former, the open command directly returned a XResultSet.
616 aCursorAny >>= aResult;
617
618 OSL_ENSURE( !aResult.is(),
619 "Content::createCursor - open-Command must "
620 "return a Reference< XDynnamicResultSet >!" );
621 }
622
623 return aResult;
624}
625
626
628 const Sequence< OUString >& rPropertyNames,
629 ResultSetInclude eMode )
630{
632 createCursorAny( rPropertyNames, eMode ) >>= aResult;
633
634 OSL_ENSURE( aResult.is(), "Content::createDynamicCursor - no cursor!" );
635
636 return aResult;
637}
638
639
641 const Sequence< OUString >& rPropertyNames,
642 const Sequence< NumberedSortingInfo >& rSortInfo,
643 const Reference< XAnyCompareFactory >& rAnyCompareFactory,
644 ResultSetInclude eMode )
645{
648
649 Any aCursorAny = createCursorAny( rPropertyNames, eMode );
650
651 aCursorAny >>= aDynSet;
652
653 if( aDynSet.is() )
654 {
656
657 if( m_xImpl->getComponentContext().is() )
658 {
660 SortedDynamicResultSetFactory::create( m_xImpl->getComponentContext());
661
662 aDynResult = aSortFactory->createSortedDynamicResultSet( aDynSet,
663 rSortInfo,
664 rAnyCompareFactory );
665 }
666
667 OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!" );
668
669 if( aDynResult.is() )
670 aResult = aDynResult->getStaticResultSet();
671 else
672 aResult = aDynSet->getStaticResultSet();
673 }
674
675 OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
676
677 if ( !aResult.is() )
678 {
679 // Former, the open command directly returned a XResultSet.
680 aCursorAny >>= aResult;
681
682 OSL_ENSURE( !aResult.is(),
683 "Content::createCursor - open-Command must "
684 "return a Reference< XDynnamicResultSet >!" );
685 }
686
687 return aResult;
688}
689
690
692{
693 if ( !isDocument() )
695
696 Reference< XActiveDataSink > xSink = new ActiveDataSink;
697
698 OpenCommandArgument2 aArg;
699 aArg.Mode = OpenMode::DOCUMENT;
700 aArg.Priority = 0; // unused
701 aArg.Sink = xSink;
702 aArg.Properties = Sequence< Property >( 0 ); // unused
703
705 aCommand.Name = "open";
706 aCommand.Handle = -1; // n/a
707 aCommand.Argument <<= aArg;
708
709 m_xImpl->executeCommand( aCommand );
710
711 return xSink->getInputStream();
712}
713
714
716{
717 if ( !isDocument() )
719
720 Reference< XActiveDataSink > xSink = new ActiveDataSink;
721
722 OpenCommandArgument2 aArg;
723 aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
724 aArg.Priority = 0; // unused
725 aArg.Sink = xSink;
726 aArg.Properties = Sequence< Property >( 0 ); // unused
727
729 aCommand.Name = "open";
730 aCommand.Handle = -1; // n/a
731 aCommand.Argument <<= aArg;
732
733 m_xImpl->executeCommand( aCommand );
734
735 return xSink->getInputStream();
736}
737
738
740{
741 if ( !isDocument() )
742 return Reference< XStream >();
743
745
746 OpenCommandArgument2 aArg;
747 aArg.Mode = OpenMode::DOCUMENT;
748 aArg.Priority = 0; // unused
749 aArg.Sink = xStreamer;
750 aArg.Properties = Sequence< Property >( 0 ); // unused
751
753 aCommand.Name = "open";
754 aCommand.Handle = -1; // n/a
755 aCommand.Argument <<= aArg;
756
757 m_xImpl->executeCommand( aCommand );
758
759 return xStreamer->getStream();
760}
761
762
764{
765 if ( !isDocument() )
766 return Reference< XStream >();
767
769
770 OpenCommandArgument2 aArg;
771 aArg.Mode = OpenMode::DOCUMENT_SHARE_DENY_NONE;
772 aArg.Priority = 0; // unused
773 aArg.Sink = xStreamer;
774 aArg.Properties = Sequence< Property >( 0 ); // unused
775
777 aCommand.Name = "open";
778 aCommand.Handle = -1; // n/a
779 aCommand.Argument <<= aArg;
780
781 m_xImpl->executeCommand( aCommand );
782
783 return xStreamer->getStream();
784}
785
786
788{
789 if ( !isDocument() )
790 return false;
791
792 OpenCommandArgument2 aArg;
793 aArg.Mode = OpenMode::DOCUMENT;
794 aArg.Priority = 0; // unused
795 aArg.Sink = rSink;
796 aArg.Properties = Sequence< Property >( 0 ); // unused
797
799 aCommand.Name = "open";
800 aCommand.Handle = -1; // n/a
801 aCommand.Argument <<= aArg;
802
803 m_xImpl->executeCommand( aCommand );
804
805 return true;
806}
807
808
810{
811 if ( !isDocument() )
812 return false;
813
814 OpenCommandArgument2 aArg;
815 aArg.Mode = OpenMode::DOCUMENT;
816 aArg.Priority = 0; // unused
817 aArg.Sink = rStream;
818 aArg.Properties = Sequence< Property >( 0 ); // unused
819
821 aCommand.Name = "open";
822 aCommand.Handle = -1; // n/a
823 aCommand.Argument <<= aArg;
824
825 m_xImpl->executeCommand( aCommand );
826
827 return true;
828}
829
830
832 bool bReplaceExisting )
833{
834 InsertCommandArgument aArg;
835 aArg.Data = rStream.is() ? rStream : new EmptyInputStream;
836 aArg.ReplaceExisting = bReplaceExisting;
837
839 aCommand.Name = "insert";
840 aCommand.Handle = -1; // n/a
841 aCommand.Argument <<= aArg;
842
843 m_xImpl->executeCommand( aCommand );
844
845 m_xImpl->inserted();
846}
847
848
850{
851 // First, try it using "CreatableContentsInfo" property -> the "new" way.
853 if ( getPropertyValue(
854 "CreatableContentsInfo" )
855 >>= aInfo )
856 return aInfo;
857
858 // Second, try it using XContentCreator interface -> the "old" way (not
859 // providing the chance to supply an XCommandEnvironment.
860 Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
861 if ( xCreator.is() )
862 aInfo = xCreator->queryCreatableContentsInfo();
863
864 return aInfo;
865}
866
867
868bool Content::insertNewContent( const OUString& rContentType,
870 rPropertyNames,
871 const Sequence< Any >& rPropertyValues,
872 Content& rNewContent )
873{
874 return insertNewContent( rContentType,
875 rPropertyNames,
876 rPropertyValues,
877 new EmptyInputStream,
878 rNewContent );
879}
880
881
882bool Content::insertNewContent( const OUString& rContentType,
884 rPropertyNames,
885 const Sequence< Any >& rPropertyValues,
886 const Reference< XInputStream >& rData,
887 Content& rNewContent )
888{
889 if ( rContentType.isEmpty() )
890 return false;
891
892 // First, try it using "createNewContent" command -> the "new" way.
893 ContentInfo aInfo;
894 aInfo.Type = rContentType;
895 aInfo.Attributes = 0;
896
898 aCommand.Name = "createNewContent";
899 aCommand.Handle = -1; // n/a
900 aCommand.Argument <<= aInfo;
901
903 try
904 {
905 m_xImpl->executeCommand( aCommand ) >>= xNew;
906 }
907 catch ( RuntimeException const & )
908 {
909 throw;
910 }
911 catch ( Exception const & )
912 {
913 }
914
915 if ( !xNew.is() )
916 {
917 // Second, try it using XContentCreator interface -> the "old"
918 // way (not providing the chance to supply an XCommandEnvironment.
919 Reference< XContentCreator > xCreator( m_xImpl->getContent(), UNO_QUERY );
920
921 if ( !xCreator.is() )
922 return false;
923
924 xNew = xCreator->createNewContent( aInfo );
925
926 if ( !xNew.is() )
927 return false;
928 }
929
930 Content aNewContent(
931 xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
932 aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
933 aNewContent.executeCommand( "insert",
934 Any(
935 InsertCommandArgument(
936 rData.is() ? rData : new EmptyInputStream,
937 false /* ReplaceExisting */ ) ) );
938 aNewContent.m_xImpl->inserted();
939
940 rNewContent = aNewContent;
941 return true;
942}
943
944
945void Content::transferContent( const Content& rSourceContent,
946 InsertOperation eOperation,
947 const OUString & rTitle,
948 const sal_Int32 nNameClashAction,
949 const OUString & rMimeType,
950 bool bMajorVersion,
951 const OUString & rVersionComment,
952 OUString* pResultURL,
953 const OUString & rDocumentId ) const
954{
956 UniversalContentBroker::create( m_xImpl->getComponentContext() ) );
957
958 // Execute command "globalTransfer" at UCB.
959
960 TransferCommandOperation eTransOp = TransferCommandOperation();
961 OUString sCommand( "globalTransfer" );
962 bool bCheckIn = false;
963 switch ( eOperation )
964 {
966 eTransOp = TransferCommandOperation_COPY;
967 break;
968
970 eTransOp = TransferCommandOperation_MOVE;
971 break;
972
974 eTransOp = TransferCommandOperation_COPY;
975 sCommand = "checkin";
976 bCheckIn = true;
977 break;
978 }
980 aCommand.Name = sCommand;
981 aCommand.Handle = -1; // n/a
982
983 if ( !bCheckIn )
984 {
985 GlobalTransferCommandArgument2 aTransferArg(
986 eTransOp,
987 rSourceContent.getURL(), // SourceURL
988 getURL(), // TargetFolderURL,
989 rTitle,
990 nNameClashAction,
991 rMimeType,
992 rDocumentId );
993 aCommand.Argument <<= aTransferArg;
994 }
995 else
996 {
997 CheckinArgument aCheckinArg( bMajorVersion, rVersionComment,
998 rSourceContent.getURL(), getURL(), rTitle, rMimeType );
999 aCommand.Argument <<= aCheckinArg;
1000 }
1001
1002 Any aRet = pBroker->execute( aCommand, 0, m_xImpl->getEnvironment() );
1003 if ( pResultURL != nullptr )
1004 aRet >>= *pResultURL;
1005}
1006
1007
1009{
1010 bool bFolder = false;
1011 if ( getPropertyValue("IsFolder")
1012 >>= bFolder )
1013 return bFolder;
1014
1016 Any( UnknownPropertyException(
1017 "Unable to retrieve value of property 'IsFolder'!",
1018 get() ) ),
1019 m_xImpl->getEnvironment() );
1020
1022}
1023
1024
1026{
1027 bool bDoc = false;
1028 if ( getPropertyValue("IsDocument")
1029 >>= bDoc )
1030 return bDoc;
1031
1033 Any( UnknownPropertyException(
1034 "Unable to retrieve value of property 'IsDocument'!",
1035 get() ) ),
1036 m_xImpl->getEnvironment() );
1037
1039}
1040
1042{
1044 aCommand.Name = "lock";
1045 aCommand.Handle = -1; // n/a
1046
1047 m_xImpl->executeCommand( aCommand );
1048
1049}
1050
1052{
1053
1055 aCommand.Name = "unlock";
1056 aCommand.Handle = -1; // n/a
1057
1058 m_xImpl->executeCommand( aCommand );
1059
1060}
1061
1062
1063// Content_Impl Implementation.
1064
1065
1067 const Reference< XContent >& rContent,
1069: m_xCtx( rCtx ),
1070 m_xContent( rContent ),
1071 m_xEnv( rEnv )
1072{
1073 assert(rCtx.is());
1074 if ( m_xContent.is() )
1075 {
1077 m_xContent->addContentEventListener( m_xContentEventListener );
1078
1079#if OSL_DEBUG_LEVEL > 0
1080 // Only done on demand in product version for performance reasons,
1081 // but a nice debug helper.
1082 getURL();
1083#endif
1084 }
1085}
1086
1087
1089{
1090 std::unique_lock aGuard( m_aMutex );
1091
1092 m_xCommandProcessor = nullptr;
1093
1094 // #92581# - Don't reset m_aURL!!!
1095
1096 if ( m_xContent.is() )
1097 {
1098 try
1099 {
1100 m_xContent->removeContentEventListener( m_xContentEventListener );
1101 }
1102 catch ( RuntimeException const & )
1103 {
1104 }
1105 }
1106
1107 if ( xContent.is() )
1108 {
1109 m_xContent = xContent;
1110 m_xContent->addContentEventListener( m_xContentEventListener );
1111
1112#if OSL_DEBUG_LEVEL > 0
1113 // Only done on demand in product version for performance reasons,
1114 // but a nice debug helper.
1115 getURL_NoLock();
1116#endif
1117 }
1118 else
1119 {
1120 // We need m_xContent's URL in order to be able to create the
1121 // content object again if demanded ( --> Content_Impl::getContent() )
1122 getURL_NoLock();
1123
1124 m_xContent = nullptr;
1125 }
1126}
1127
1128
1129// virtual
1131{
1132 if ( m_xContent.is() )
1133 {
1134 try
1135 {
1136 m_xContent->removeContentEventListener( m_xContentEventListener );
1137 }
1138 catch ( RuntimeException const & )
1139 {
1140 }
1141 }
1142}
1143
1144
1145void Content_Impl::disposing( const EventObject& Source )
1146{
1147 Reference<XContent> xContent;
1148
1149 {
1150 std::unique_lock aGuard( m_aMutex );
1151 if(Source.Source != m_xContent)
1152 return;
1153
1154 xContent = m_xContent;
1155
1156 m_aURL.clear();
1157 m_xCommandProcessor = nullptr;
1158 m_xContent = nullptr;
1159 }
1160
1161 if ( xContent.is() )
1162 {
1163 try
1164 {
1165 xContent->removeContentEventListener( m_xContentEventListener );
1166 }
1167 catch ( RuntimeException const & )
1168 {
1169 }
1170 }
1171}
1172
1173
1174const OUString& Content_Impl::getURL() const
1175{
1176 if ( m_aURL.isEmpty() && m_xContent.is() )
1177 {
1178 std::unique_lock aGuard( m_aMutex );
1179
1180 return getURL_NoLock();
1181 }
1182
1183 return m_aURL;
1184}
1185
1186const OUString& Content_Impl::getURL_NoLock() const
1187{
1188 if ( m_aURL.isEmpty() && m_xContent.is() )
1189 {
1190 Reference< XContentIdentifier > xId = m_xContent->getIdentifier();
1191 if ( xId.is() )
1192 m_aURL = xId->getContentIdentifier();
1193 }
1194
1195 return m_aURL;
1196}
1197
1199{
1200 if ( !m_xContent.is() && !m_aURL.isEmpty() )
1201 {
1202 std::unique_lock aGuard( m_aMutex );
1203 return getContent_NoLock();
1204 }
1205 return m_xContent;
1206}
1207
1209{
1210 if ( !m_xContent.is() && !m_aURL.isEmpty() )
1211 {
1213 UniversalContentBroker::create( getComponentContext() ) );
1214
1215 OSL_ENSURE( pBroker->queryContentProviders().hasElements(),
1216 "Content Broker not configured (no providers)!" );
1217
1219 = pBroker->createContentIdentifier( m_aURL );
1220
1221 OSL_ENSURE( xId.is(), "No Content Identifier!" );
1222
1223 if ( xId.is() )
1224 {
1225 try
1226 {
1227 m_xContent = pBroker->queryContent( xId );
1228 }
1229 catch ( IllegalIdentifierException const & )
1230 {
1231 }
1232
1233 if ( m_xContent.is() )
1234 m_xContent->addContentEventListener(
1236 }
1237 }
1238
1239 return m_xContent;
1240}
1241
1242
1244{
1245 if ( !m_xCommandProcessor.is() )
1246 {
1247 std::unique_lock aGuard( m_aMutex );
1248
1249 if ( !m_xCommandProcessor.is() )
1250 m_xCommandProcessor.set( getContent_NoLock(), UNO_QUERY );
1251 }
1252
1253 return m_xCommandProcessor;
1254}
1255
1256
1257Any Content_Impl::executeCommand( const Command& rCommand )
1258{
1260 if ( !xProc.is() )
1261 return Any();
1262
1263 // Execute command
1264 return xProc->execute( rCommand, 0, m_xEnv );
1265}
1266
1267
1270{
1271 return m_xEnv;
1272}
1273
1274
1276 const Reference< XCommandEnvironment >& xNewEnv )
1277{
1278 std::unique_lock aGuard( m_aMutex );
1279 m_xEnv = xNewEnv;
1280}
1281
1282
1284{
1285 // URL might have changed during 'insert' => recalculate in next getURL()
1286 std::unique_lock aGuard( m_aMutex );
1287 m_aURL.clear();
1288}
1289
1290
1291// ContentEventListener_Impl Implementation.
1292
1293
1294// XInterface methods.
1295
1296void SAL_CALL ContentEventListener_Impl::acquire()
1297 noexcept
1298{
1299 OWeakObject::acquire();
1300}
1301
1302void SAL_CALL ContentEventListener_Impl::release()
1303 noexcept
1304{
1305 OWeakObject::release();
1306}
1307
1308css::uno::Any SAL_CALL ContentEventListener_Impl::queryInterface( const css::uno::Type & rType )
1309{
1310 css::uno::Any aRet = cppu::queryInterface( rType,
1311 static_cast< XContentEventListener* >(this),
1312 static_cast< XEventListener* >(this)
1313 );
1314 return aRet.hasValue() ? aRet : OWeakObject::queryInterface( rType );
1315}
1316
1317// XContentEventListener methods.
1318
1319
1320// virtual
1321void SAL_CALL ContentEventListener_Impl::contentEvent( const ContentEvent& evt )
1322{
1323 if ( evt.Source != m_rContent.m_xContent )
1324 return;
1325
1326 switch ( evt.Action )
1327 {
1328 case ContentAction::DELETED:
1330 break;
1331
1332 case ContentAction::EXCHANGED:
1333 m_rContent.reinit( evt.Content );
1334 break;
1335
1336 default:
1337 break;
1338 }
1339}
1340
1341
1342// XEventListenr methods.
1343
1344
1345// virtual
1346void SAL_CALL ContentEventListener_Impl::disposing( const EventObject& Source )
1347{
1348 m_rContent.disposing(Source);
1349}
1350
1351} /* namespace ucbhelper */
1352
1353/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
Reference< XComponentContext > m_xCtx
uno::Reference< ucb::XContent > m_xContent
This class implements the interface css::io::XActiveDataStreamer.
const Reference< XContent > & getContent_NoLock()
Definition: content.cxx:1208
const Reference< XCommandEnvironment > & getEnvironment() const
Definition: content.cxx:1269
friend ContentEventListener_Impl
Definition: content.cxx:154
Any executeCommand(const Command &rCommand)
Definition: content.cxx:1257
Reference< XCommandProcessor > getCommandProcessor()
Definition: content.cxx:1243
virtual ~Content_Impl() override
Definition: content.cxx:1130
Reference< XCommandProcessor > m_xCommandProcessor
Definition: content.cxx:159
Reference< XComponentContext > m_xCtx
Definition: content.cxx:157
Reference< XContent > getContent()
Definition: content.cxx:1198
Reference< XContentEventListener > m_xContentEventListener
Definition: content.cxx:161
Reference< XContent > m_xContent
Definition: content.cxx:158
Reference< XComponentContext > const & getComponentContext() const
Definition: content.cxx:181
const OUString & getURL_NoLock() const
Definition: content.cxx:1186
Reference< XCommandEnvironment > m_xEnv
Definition: content.cxx:160
const OUString & getURL() const
Definition: content.cxx:1174
void reinit(const Reference< XContent > &xContent)
Definition: content.cxx:1088
void setEnvironment(const Reference< XCommandEnvironment > &xNewEnv)
Definition: content.cxx:1275
void disposing(const EventObject &Source)
Definition: content.cxx:1145
This class simplifies access to UCB contents by providing a more convenient API for frequently used f...
Definition: content.hxx:99
bool isFolder()
This method returns the value of the content's property "IsFolder".
Definition: content.cxx:1008
css::uno::Any setPropertyValue(const OUString &rPropertyName, const css::uno::Any &rValue)
This method can be used to set a single property value.
Definition: content.cxx:442
const OUString & getURL() const
This method returns the URL of the content.
Definition: content.cxx:383
void transferContent(const Content &rSourceContent, InsertOperation eOperation, const OUString &rTitle, const sal_Int32 nNameClashAction, const OUString &rMimeType=OUString(), bool bMajorVersion=false, const OUString &rCommentVersion=OUString(), OUString *pResultURL=nullptr, const OUString &rDocumentId=OUString()) const
This method transfers (copies/moves) a content.
Definition: content.cxx:945
Content & operator=(const Content &rOther)
Assignment operator.
Definition: content.cxx:365
css::uno::Reference< css::sdbc::XRow > getPropertyValuesInterface(const css::uno::Sequence< OUString > &rPropertyNames)
This method can be used to read multiple property values.
Definition: content.cxx:475
const css::uno::Reference< css::ucb::XCommandEnvironment > & getCommandEnvironment() const
This method returns the environment to use when executing commands.
Definition: content.cxx:389
css::uno::Any getPropertyValue(const OUString &rPropertyName)
This method can be used to read a single property value.
Definition: content.cxx:433
css::uno::Reference< css::io::XStream > openWriteableStream()
This methods gives read/write access to the content stream of a content (i.e the content of a file lo...
Definition: content.cxx:739
css::uno::Reference< css::io::XInputStream > openStreamNoLock()
This methods gives read access to the content stream of a content (i.e the content of a file located ...
Definition: content.cxx:715
css::uno::Reference< css::beans::XPropertySetInfo > getProperties()
This methods provides access to meta data of the properties supported by this content.
Definition: content.cxx:417
void unlock()
This method unlock the resource.
Definition: content.cxx:1051
css::uno::Any executeCommand(const OUString &rCommandName, const css::uno::Any &rCommandArgument)
This method can be used to execute any command supported by the content.
Definition: content.cxx:554
~Content()
Destructor.
Definition: content.cxx:360
css::uno::Reference< css::ucb::XCommandInfo > getCommands()
This methods provides access to meta data of the commands supported by this content.
Definition: content.cxx:402
static bool create(const OUString &rURL, const css::uno::Reference< css::ucb::XCommandEnvironment > &rEnv, const css::uno::Reference< css::uno::XComponentContext > &rCtx, Content &rContent)
Constructor.
css::uno::Any createCursorAny(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode)
Definition: content.cxx:566
css::uno::Sequence< css::uno::Any > setPropertyValues(const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rValues)
This method can be used to set multiple property values.
void lock()
This method lock the resource.
Definition: content.cxx:1041
css::uno::Reference< css::io::XStream > openWriteableStreamNoLock()
This methods gives read/write access to the content stream of a content (i.e the content of a file lo...
Definition: content.cxx:763
bool insertNewContent(const OUString &rContentType, const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::uno::Any > &rPropertyValues, Content &rNewContent)
This method creates, initializes and inserts ( commits ) a new content (i.e.
css::uno::Sequence< css::ucb::ContentInfo > queryCreatableContentsInfo()
This method returns the different types of contents this content can create.
Definition: content.cxx:849
bool isDocument()
This method returns the value of the content's property "IsDocument".
Definition: content.cxx:1025
css::uno::Reference< css::ucb::XContent > get() const
This method provides access to the "native" UCB content interface(s).
Definition: content.cxx:377
css::uno::Reference< css::io::XInputStream > openStream()
This methods gives read access to the content stream of a content (i.e the content of a file located ...
Definition: content.cxx:691
css::uno::Reference< css::sdbc::XResultSet > createSortedCursor(const css::uno::Sequence< OUString > &rPropertyNames, const css::uno::Sequence< css::ucb::NumberedSortingInfo > &rSortInfo, const css::uno::Reference< css::ucb::XAnyCompareFactory > &rAnyCompareFactory, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
Definition: content.cxx:640
css::uno::Reference< css::sdbc::XResultSet > createCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
This methods gives access to the children of a folder content.
Definition: content.cxx:598
void setCommandEnvironment(const css::uno::Reference< css::ucb::XCommandEnvironment > &xNewEnv)
This method sets a new command environment.
Definition: content.cxx:395
Content()
Constructor.
Definition: content.cxx:295
rtl::Reference< Content_Impl > m_xImpl
Definition: content.hxx:100
css::uno::Sequence< css::uno::Any > getPropertyValues(const css::uno::Sequence< OUString > &rPropertyNames)
This method can be used to read multiple property values.
css::uno::Reference< css::ucb::XDynamicResultSet > createDynamicCursor(const css::uno::Sequence< OUString > &rPropertyNames, ResultSetInclude eMode=INCLUDE_FOLDERS_AND_DOCUMENTS)
This methods gives access to the children of a folder content.
Definition: content.cxx:627
void writeStream(const css::uno::Reference< css::io::XInputStream > &rStream, bool bReplaceExisting)
This methods gives write access to the content stream of a content (i.e the content of a file located...
Definition: content.cxx:831
Content_Impl & m_rContent
Definition: content.cxx:128
int nCount
float u
Mode eMode
sal_Int64 n
tools::SvRef< SvBaseLink > xSink
DECL_LISTENERMULTIPLEXER_END void SAL_CALL inserted(::sal_Int32 ID) override
#define SAL_WARN(area, stream)
bool executeCommand(const OUString &rCommand)
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
css::uno::Environment getEnvironment(OUString const &name, std::u16string_view implementation)
static Reference< XContent > getContentThrow(const Reference< XUniversalContentBroker > &rBroker, const Reference< XContentIdentifier > &xId)
Definition: content.cxx:244
InsertOperation
These are the possible values for the parameter eOperation of method ucbhelper::Content::insertNewCon...
Definition: content.hxx:85
static Reference< XContentIdentifier > getContentIdentifierThrow(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:214
static Reference< XContentIdentifier > getContentIdentifierNoThrow(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:235
ResultSetInclude
These are the possible values for the parameter eMode of method ucbhelper::Content::createCursor.
Definition: content.hxx:74
@ INCLUDE_FOLDERS_ONLY
Definition: content.hxx:75
@ INCLUDE_DOCUMENTS_ONLY
Definition: content.hxx:76
void cancelCommandExecution(const uno::Any &rException, const uno::Reference< ucb::XCommandEnvironment > &xEnv)
static Reference< XContent > getContentNoThrow(const Reference< XUniversalContentBroker > &rBroker, const Reference< XContentIdentifier > &xId)
Definition: content.cxx:274
static void ensureContentProviderForURL(const Reference< XUniversalContentBroker > &rBroker, const OUString &rURL)
Definition: content.cxx:198
OUString aCommand
#define O3TL_UNREACHABLE