1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
24 #include <osl/diagnose.h>
25 #include <osl/mutex.hxx>
26 #include <sal/log.hxx>
27 #include <salhelper/simplereferenceobject.hxx>
28 #include <cppuhelper/weak.hxx>
29 #include <cppuhelper/queryinterface.hxx>
31 #include <cppuhelper/implbase.hxx>
32 #include <com/sun/star/ucb/CheckinArgument.hpp>
33 #include <com/sun/star/ucb/ContentCreationError.hpp>
34 #include <com/sun/star/ucb/ContentCreationException.hpp>
35 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
36 #include <com/sun/star/ucb/XCommandEnvironment.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/CommandInfo.hpp>
41 #include <com/sun/star/ucb/ContentAction.hpp>
42 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
43 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
44 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
45 #include <com/sun/star/ucb/NameClash.hpp>
46 #include <com/sun/star/ucb/OpenMode.hpp>
47 #include <com/sun/star/ucb/XContentCreator.hpp>
48 #include <com/sun/star/ucb/XContentEventListener.hpp>
49 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
50 #include <com/sun/star/ucb/XContentProvider.hpp>
51 #include <com/sun/star/ucb/XContentProviderManager.hpp>
52 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
53 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
54 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
55 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
56 #include <com/sun/star/beans/XPropertySetInfo.hpp>
57 #include <com/sun/star/beans/Property.hpp>
58 #include <com/sun/star/beans/PropertyValue.hpp>
59 #include <com/sun/star/sdbc/XResultSet.hpp>
60 #include <com/sun/star/sdbc/XRow.hpp>
61 #include <com/sun/star/lang/IllegalArgumentException.hpp>
62 #include <com/sun/star/beans/UnknownPropertyException.hpp>
63 #include <ucbhelper/macros.hxx>
64 #include <ucbhelper/content.hxx>
65 #include <ucbhelper/activedatasink.hxx>
66 #include <ucbhelper/activedatastreamer.hxx>
67 #include <ucbhelper/interactionrequest.hxx>
68 #include <ucbhelper/cancelcommandexecution.hxx>
70 using namespace com::sun::star::container
;
71 using namespace com::sun::star::beans
;
72 using namespace com::sun::star::io
;
73 using namespace com::sun::star::lang
;
74 using namespace com::sun::star::sdbc
;
75 using namespace com::sun::star::task
;
76 using namespace com::sun::star::ucb
;
77 using namespace com::sun::star::uno
;
82 class EmptyInputStream
: public ::cppu::WeakImplHelper
< XInputStream
>
85 virtual sal_Int32 SAL_CALL
readBytes(
86 Sequence
< sal_Int8
> & data
, sal_Int32 nBytesToRead
) override
;
87 virtual sal_Int32 SAL_CALL
readSomeBytes(
88 Sequence
< sal_Int8
> & data
, sal_Int32 nMaxBytesToRead
) override
;
89 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
) override
;
90 virtual sal_Int32 SAL_CALL
available() override
;
91 virtual void SAL_CALL
closeInput() override
;
94 sal_Int32
EmptyInputStream::readBytes(
95 Sequence
< sal_Int8
> & data
, sal_Int32
)
101 sal_Int32
EmptyInputStream::readSomeBytes(
102 Sequence
< sal_Int8
> & data
, sal_Int32
)
108 void EmptyInputStream::skipBytes( sal_Int32
)
112 sal_Int32
EmptyInputStream::available()
117 void EmptyInputStream::closeInput()
122 // class ContentEventListener_Impl.
125 class ContentEventListener_Impl
: public cppu::OWeakObject
,
126 public XContentEventListener
128 Content_Impl
& m_rContent
;
131 explicit ContentEventListener_Impl( Content_Impl
& rContent
)
132 : m_rContent( rContent
) {}
135 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& rType
) override
;
136 virtual void SAL_CALL
acquire()
138 virtual void SAL_CALL
release()
141 // XContentEventListener
142 virtual void SAL_CALL
contentEvent( const ContentEvent
& evt
) override
;
144 // XEventListener ( base of XContentEventListener )
145 virtual void SAL_CALL
disposing( const EventObject
& Source
) override
;
149 // class Content_Impl.
152 class Content_Impl
: public salhelper::SimpleReferenceObject
154 friend class ContentEventListener_Impl
;
156 mutable OUString m_aURL
;
157 Reference
< XComponentContext
> m_xCtx
;
158 Reference
< XContent
> m_xContent
;
159 Reference
< XCommandProcessor
> m_xCommandProcessor
;
160 Reference
< XCommandEnvironment
> m_xEnv
;
161 Reference
< XContentEventListener
> m_xContentEventListener
;
162 mutable osl::Mutex m_aMutex
;
165 void reinit( const Reference
< XContent
>& xContent
);
166 void disposing(const EventObject
& Source
);
170 Content_Impl( const Reference
< XComponentContext
>& rCtx
,
171 const Reference
< XContent
>& rContent
,
172 const Reference
< XCommandEnvironment
>& rEnv
);
174 virtual ~Content_Impl() override
;
176 const OUString
& getURL() const;
177 Reference
< XContent
> getContent();
178 Reference
< XCommandProcessor
> getCommandProcessor();
179 Reference
< XComponentContext
> const & getComponentContext() const
180 { assert(m_xCtx
.is()); return m_xCtx
; }
182 Any
executeCommand( const Command
& rCommand
);
184 inline const Reference
< XCommandEnvironment
>& getEnvironment() const;
185 inline void setEnvironment(
186 const Reference
< XCommandEnvironment
>& xNewEnv
);
194 /// @throws ContentCreationException
195 /// @throws RuntimeException
196 static void ensureContentProviderForURL( const Reference
< XUniversalContentBroker
>& rBroker
,
197 const OUString
& rURL
)
199 Reference
< XContentProvider
> xProv
200 = rBroker
->queryContentProvider( rURL
);
203 throw ContentCreationException(
204 "No Content Provider available for URL: " + rURL
,
205 Reference
< XInterface
>(),
206 ContentCreationError_NO_CONTENT_PROVIDER
);
210 /// @throws ContentCreationException
211 /// @throws RuntimeException
212 static Reference
< XContentIdentifier
> getContentIdentifierThrow(
213 const Reference
< XUniversalContentBroker
> & rBroker
,
214 const OUString
& rURL
)
216 Reference
< XContentIdentifier
> xId
217 = rBroker
->createContentIdentifier( rURL
);
221 ensureContentProviderForURL( rBroker
, rURL
);
223 throw ContentCreationException(
224 "Unable to create Content Identifier!",
225 Reference
< XInterface
>(),
226 ContentCreationError_IDENTIFIER_CREATION_FAILED
);
232 /// @throws RuntimeException
233 static Reference
< XContentIdentifier
> getContentIdentifierNoThrow(
234 const Reference
< XUniversalContentBroker
> & rBroker
,
235 const OUString
& rURL
)
237 return rBroker
->createContentIdentifier(rURL
);
240 /// @throws ContentCreationException
241 /// @throws RuntimeException
242 static Reference
< XContent
> getContentThrow(
243 const Reference
< XUniversalContentBroker
> & rBroker
,
244 const Reference
< XContentIdentifier
> & xId
)
246 Reference
< XContent
> xContent
;
250 xContent
= rBroker
->queryContent( xId
);
252 catch ( IllegalIdentifierException
const & e
)
258 if ( !xContent
.is() )
260 ensureContentProviderForURL( rBroker
, xId
->getContentIdentifier() );
262 throw ContentCreationException(
263 "Unable to create Content for <" + xId
->getContentIdentifier() + ">: " + msg
,
264 Reference
< XInterface
>(),
265 ContentCreationError_CONTENT_CREATION_FAILED
);
271 /// @throws RuntimeException
272 static Reference
< XContent
> getContentNoThrow(
273 const Reference
< XUniversalContentBroker
> & rBroker
,
274 const Reference
< XContentIdentifier
> & xId
)
276 Reference
< XContent
> xContent
;
279 xContent
= rBroker
->queryContent( xId
);
281 catch ( IllegalIdentifierException
const & e
)
283 SAL_WARN("ucbhelper", "getContentNoThrow: " << e
);
290 // Content Implementation.
294 : m_xImpl( new Content_Impl
)
299 Content::Content( const OUString
& rURL
,
300 const Reference
< XCommandEnvironment
>& rEnv
,
301 const Reference
< XComponentContext
>& rCtx
)
303 Reference
< XUniversalContentBroker
> pBroker(
304 UniversalContentBroker::create( rCtx
) );
306 Reference
< XContentIdentifier
> xId
307 = getContentIdentifierThrow(pBroker
, rURL
);
309 Reference
< XContent
> xContent
= getContentThrow(pBroker
, xId
);
311 m_xImpl
= new Content_Impl( rCtx
, xContent
, rEnv
);
315 Content::Content( const Reference
< XContent
>& rContent
,
316 const Reference
< XCommandEnvironment
>& rEnv
,
317 const Reference
< XComponentContext
>& rCtx
)
319 m_xImpl
= new Content_Impl( rCtx
, rContent
, rEnv
);
323 Content::Content( const Content
& rOther
)
325 m_xImpl
= rOther
.m_xImpl
;
328 Content::Content( Content
&& rOther
)
330 m_xImpl
= std::move(rOther
.m_xImpl
);
334 bool Content::create( const OUString
& rURL
,
335 const Reference
< XCommandEnvironment
>& rEnv
,
336 const Reference
< XComponentContext
>& rCtx
,
339 Reference
< XUniversalContentBroker
> pBroker(
340 UniversalContentBroker::create( rCtx
) );
342 Reference
< XContentIdentifier
> xId
343 = getContentIdentifierNoThrow(pBroker
, rURL
);
347 Reference
< XContent
> xContent
= getContentNoThrow(pBroker
, xId
);
348 if ( !xContent
.is() )
352 = new Content_Impl( rCtx
, xContent
, rEnv
);
363 Content
& Content::operator=( const Content
& rOther
)
365 m_xImpl
= rOther
.m_xImpl
;
369 Content
& Content::operator=( Content
&& rOther
)
371 m_xImpl
= std::move(rOther
.m_xImpl
);
375 Reference
< XContent
> Content::get() const
377 return m_xImpl
->getContent();
381 const OUString
& Content::getURL() const
383 return m_xImpl
->getURL();
387 const Reference
< XCommandEnvironment
>& Content::getCommandEnvironment() const
389 return m_xImpl
->getEnvironment();
393 void Content::setCommandEnvironment(
394 const Reference
< XCommandEnvironment
>& xNewEnv
)
396 m_xImpl
->setEnvironment( xNewEnv
);
400 Reference
< XCommandInfo
> Content::getCommands()
403 aCommand
.Name
= "getCommandInfo";
404 aCommand
.Handle
= -1; // n/a
405 aCommand
.Argument
= Any();
407 Any aResult
= m_xImpl
->executeCommand( aCommand
);
409 Reference
< XCommandInfo
> xInfo
;
415 Reference
< XPropertySetInfo
> Content::getProperties()
418 aCommand
.Name
= "getPropertySetInfo";
419 aCommand
.Handle
= -1; // n/a
420 aCommand
.Argument
= Any();
422 Any aResult
= m_xImpl
->executeCommand( aCommand
);
424 Reference
< XPropertySetInfo
> xInfo
;
430 Any
Content::getPropertyValue( const OUString
& rPropertyName
)
432 Sequence
<OUString
> aNames
{ rPropertyName
};
434 Sequence
< Any
> aRet
= getPropertyValues( aNames
);
435 return aRet
.getConstArray()[ 0 ];
439 Any
Content::setPropertyValue( const OUString
& rName
,
442 Sequence
<OUString
> aNames
{ rName
};
444 Sequence
< Any
> aValues( 1 );
445 aValues
.getArray()[ 0 ] = rValue
;
447 Sequence
< Any
> aErrors
= setPropertyValues( aNames
, aValues
);
448 return aErrors
.getConstArray()[ 0 ];
452 Sequence
< Any
> Content::getPropertyValues(
453 const Sequence
< OUString
>& rPropertyNames
)
455 Reference
< XRow
> xRow
= getPropertyValuesInterface( rPropertyNames
);
457 sal_Int32 nCount
= rPropertyNames
.getLength();
458 Sequence
< Any
> aValues( nCount
);
462 Any
* pValues
= aValues
.getArray();
464 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
465 pValues
[ n
] = xRow
->getObject( n
+ 1, Reference
< XNameAccess
>() );
472 Reference
< XRow
> Content::getPropertyValuesInterface(
473 const Sequence
< OUString
>& rPropertyNames
)
475 sal_Int32 nCount
= rPropertyNames
.getLength();
476 Sequence
< Property
> aProps( nCount
);
477 Property
* pProps
= aProps
.getArray();
479 const OUString
* pNames
= rPropertyNames
.getConstArray();
481 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
483 Property
& rProp
= pProps
[ n
];
485 rProp
.Name
= pNames
[ n
];
486 rProp
.Handle
= -1; // n/a
488 // rProp.Attributes = ;
492 aCommand
.Name
= "getPropertyValues";
493 aCommand
.Handle
= -1; // n/a
494 aCommand
.Argument
<<= aProps
;
496 Any aResult
= m_xImpl
->executeCommand( aCommand
);
498 Reference
< XRow
> xRow
;
504 Sequence
< Any
> Content::setPropertyValues(
505 const Sequence
< OUString
>& rPropertyNames
,
506 const Sequence
< Any
>& rValues
)
508 if ( rPropertyNames
.getLength() != rValues
.getLength() )
510 ucbhelper::cancelCommandExecution(
511 makeAny( IllegalArgumentException(
512 "Length of property names sequence and value "
513 "sequence are unequal!",
516 m_xImpl
->getEnvironment() );
520 sal_Int32 nCount
= rValues
.getLength();
521 Sequence
< PropertyValue
> aProps( nCount
);
522 PropertyValue
* pProps
= aProps
.getArray();
524 const OUString
* pNames
= rPropertyNames
.getConstArray();
525 const Any
* pValues
= rValues
.getConstArray();
527 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
529 PropertyValue
& rProp
= pProps
[ n
];
531 rProp
.Name
= pNames
[ n
];
532 rProp
.Handle
= -1; // n/a
533 rProp
.Value
= pValues
[ n
];
538 aCommand
.Name
= "setPropertyValues";
539 aCommand
.Handle
= -1; // n/a
540 aCommand
.Argument
<<= aProps
;
542 Any aResult
= m_xImpl
->executeCommand( aCommand
);
544 Sequence
< Any
> aErrors
;
550 Any
Content::executeCommand( const OUString
& rCommandName
,
551 const Any
& rCommandArgument
)
554 aCommand
.Name
= rCommandName
;
555 aCommand
.Handle
= -1; // n/a
556 aCommand
.Argument
= rCommandArgument
;
558 return m_xImpl
->executeCommand( aCommand
);
562 Any
Content::createCursorAny( const Sequence
< OUString
>& rPropertyNames
,
563 ResultSetInclude eMode
)
565 sal_Int32 nCount
= rPropertyNames
.getLength();
566 Sequence
< Property
> aProps( nCount
);
567 Property
* pProps
= aProps
.getArray();
568 const OUString
* pNames
= rPropertyNames
.getConstArray();
569 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
571 Property
& rProp
= pProps
[ n
];
572 rProp
.Name
= pNames
[ n
];
573 rProp
.Handle
= -1; // n/a
576 OpenCommandArgument2 aArg
;
577 aArg
.Mode
= ( eMode
== INCLUDE_FOLDERS_ONLY
)
579 : ( eMode
== INCLUDE_DOCUMENTS_ONLY
)
580 ? OpenMode::DOCUMENTS
: OpenMode::ALL
;
581 aArg
.Priority
= 0; // unused
582 aArg
.Sink
.clear(); // unused
583 aArg
.Properties
= aProps
;
586 aCommand
.Name
= "open";
587 aCommand
.Handle
= -1; // n/a
588 aCommand
.Argument
<<= aArg
;
590 return m_xImpl
->executeCommand( aCommand
);
594 Reference
< XResultSet
> Content::createCursor(
595 const Sequence
< OUString
>& rPropertyNames
,
596 ResultSetInclude eMode
)
598 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
600 Reference
< XDynamicResultSet
> xDynSet
;
601 Reference
< XResultSet
> aResult
;
603 aCursorAny
>>= xDynSet
;
605 aResult
= xDynSet
->getStaticResultSet();
607 OSL_ENSURE( aResult
.is(), "Content::createCursor - no cursor!" );
611 // Former, the open command directly returned a XResultSet.
612 aCursorAny
>>= aResult
;
614 OSL_ENSURE( !aResult
.is(),
615 "Content::createCursor - open-Command must "
616 "return a Reference< XDynnamicResultSet >!" );
623 Reference
< XDynamicResultSet
> Content::createDynamicCursor(
624 const Sequence
< OUString
>& rPropertyNames
,
625 ResultSetInclude eMode
)
627 Reference
< XDynamicResultSet
> aResult
;
628 createCursorAny( rPropertyNames
, eMode
) >>= aResult
;
630 OSL_ENSURE( aResult
.is(), "Content::createDynamicCursor - no cursor!" );
636 Reference
< XResultSet
> Content::createSortedCursor(
637 const Sequence
< OUString
>& rPropertyNames
,
638 const Sequence
< NumberedSortingInfo
>& rSortInfo
,
639 const Reference
< XAnyCompareFactory
>& rAnyCompareFactory
,
640 ResultSetInclude eMode
)
642 Reference
< XResultSet
> aResult
;
643 Reference
< XDynamicResultSet
> aDynSet
;
645 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
647 aCursorAny
>>= aDynSet
;
651 Reference
< XDynamicResultSet
> aDynResult
;
653 if( m_xImpl
->getComponentContext().is() )
655 Reference
< XSortedDynamicResultSetFactory
> aSortFactory
=
656 SortedDynamicResultSetFactory::create( m_xImpl
->getComponentContext());
658 aDynResult
= aSortFactory
->createSortedDynamicResultSet( aDynSet
,
660 rAnyCompareFactory
);
663 OSL_ENSURE( aDynResult
.is(), "Content::createSortedCursor - no sorted cursor!" );
665 if( aDynResult
.is() )
666 aResult
= aDynResult
->getStaticResultSet();
668 aResult
= aDynSet
->getStaticResultSet();
671 OSL_ENSURE( aResult
.is(), "Content::createSortedCursor - no cursor!" );
675 // Former, the open command directly returned a XResultSet.
676 aCursorAny
>>= aResult
;
678 OSL_ENSURE( !aResult
.is(),
679 "Content::createCursor - open-Command must "
680 "return a Reference< XDynnamicResultSet >!" );
687 Reference
< XInputStream
> Content::openStream()
690 return Reference
< XInputStream
>();
692 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
694 OpenCommandArgument2 aArg
;
695 aArg
.Mode
= OpenMode::DOCUMENT
;
696 aArg
.Priority
= 0; // unused
698 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
701 aCommand
.Name
= "open";
702 aCommand
.Handle
= -1; // n/a
703 aCommand
.Argument
<<= aArg
;
705 m_xImpl
->executeCommand( aCommand
);
707 return xSink
->getInputStream();
711 Reference
< XInputStream
> Content::openStreamNoLock()
714 return Reference
< XInputStream
>();
716 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
718 OpenCommandArgument2 aArg
;
719 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
720 aArg
.Priority
= 0; // unused
722 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
725 aCommand
.Name
= "open";
726 aCommand
.Handle
= -1; // n/a
727 aCommand
.Argument
<<= aArg
;
729 m_xImpl
->executeCommand( aCommand
);
731 return xSink
->getInputStream();
735 Reference
< XStream
> Content::openWriteableStream()
738 return Reference
< XStream
>();
740 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
742 OpenCommandArgument2 aArg
;
743 aArg
.Mode
= OpenMode::DOCUMENT
;
744 aArg
.Priority
= 0; // unused
745 aArg
.Sink
= xStreamer
;
746 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
749 aCommand
.Name
= "open";
750 aCommand
.Handle
= -1; // n/a
751 aCommand
.Argument
<<= aArg
;
753 m_xImpl
->executeCommand( aCommand
);
755 return xStreamer
->getStream();
759 Reference
< XStream
> Content::openWriteableStreamNoLock()
762 return Reference
< XStream
>();
764 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
766 OpenCommandArgument2 aArg
;
767 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
768 aArg
.Priority
= 0; // unused
769 aArg
.Sink
= xStreamer
;
770 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
773 aCommand
.Name
= "open";
774 aCommand
.Handle
= -1; // n/a
775 aCommand
.Argument
<<= aArg
;
777 m_xImpl
->executeCommand( aCommand
);
779 return xStreamer
->getStream();
783 bool Content::openStream( const Reference
< XActiveDataSink
>& rSink
)
788 OpenCommandArgument2 aArg
;
789 aArg
.Mode
= OpenMode::DOCUMENT
;
790 aArg
.Priority
= 0; // unused
792 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
795 aCommand
.Name
= "open";
796 aCommand
.Handle
= -1; // n/a
797 aCommand
.Argument
<<= aArg
;
799 m_xImpl
->executeCommand( aCommand
);
805 bool Content::openStream( const Reference
< XOutputStream
>& rStream
)
810 OpenCommandArgument2 aArg
;
811 aArg
.Mode
= OpenMode::DOCUMENT
;
812 aArg
.Priority
= 0; // unused
814 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
817 aCommand
.Name
= "open";
818 aCommand
.Handle
= -1; // n/a
819 aCommand
.Argument
<<= aArg
;
821 m_xImpl
->executeCommand( aCommand
);
827 void Content::writeStream( const Reference
< XInputStream
>& rStream
,
828 bool bReplaceExisting
)
830 InsertCommandArgument aArg
;
831 aArg
.Data
= rStream
.is() ? rStream
: new EmptyInputStream
;
832 aArg
.ReplaceExisting
= bReplaceExisting
;
835 aCommand
.Name
= "insert";
836 aCommand
.Handle
= -1; // n/a
837 aCommand
.Argument
<<= aArg
;
839 m_xImpl
->executeCommand( aCommand
);
845 Sequence
< ContentInfo
> Content::queryCreatableContentsInfo()
847 // First, try it using "CreatableContentsInfo" property -> the "new" way.
848 Sequence
< ContentInfo
> aInfo
;
849 if ( getPropertyValue(
850 "CreatableContentsInfo" )
854 // Second, try it using XContentCreator interface -> the "old" way (not
855 // providing the chance to supply an XCommandEnvironment.
856 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
858 aInfo
= xCreator
->queryCreatableContentsInfo();
864 bool Content::insertNewContent( const OUString
& rContentType
,
865 const Sequence
< OUString
>&
867 const Sequence
< Any
>& rPropertyValues
,
868 Content
& rNewContent
)
870 return insertNewContent( rContentType
,
873 new EmptyInputStream
,
878 bool Content::insertNewContent( const OUString
& rContentType
,
879 const Sequence
< OUString
>&
881 const Sequence
< Any
>& rPropertyValues
,
882 const Reference
< XInputStream
>& rData
,
883 Content
& rNewContent
)
885 if ( rContentType
.isEmpty() )
888 // First, try it using "createNewContent" command -> the "new" way.
890 aInfo
.Type
= rContentType
;
891 aInfo
.Attributes
= 0;
894 aCommand
.Name
= "createNewContent";
895 aCommand
.Handle
= -1; // n/a
896 aCommand
.Argument
<<= aInfo
;
898 Reference
< XContent
> xNew
;
901 m_xImpl
->executeCommand( aCommand
) >>= xNew
;
903 catch ( RuntimeException
const & )
907 catch ( Exception
const & )
913 // Second, try it using XContentCreator interface -> the "old"
914 // way (not providing the chance to supply an XCommandEnvironment.
915 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
917 if ( !xCreator
.is() )
920 xNew
= xCreator
->createNewContent( aInfo
);
927 xNew
, m_xImpl
->getEnvironment(), m_xImpl
->getComponentContext() );
928 aNewContent
.setPropertyValues( rPropertyNames
, rPropertyValues
);
929 aNewContent
.executeCommand( "insert",
931 InsertCommandArgument(
932 rData
.is() ? rData
: new EmptyInputStream
,
933 false /* ReplaceExisting */ ) ) );
934 aNewContent
.m_xImpl
->inserted();
936 rNewContent
= aNewContent
;
941 void Content::transferContent( const Content
& rSourceContent
,
942 InsertOperation eOperation
,
943 const OUString
& rTitle
,
944 const sal_Int32 nNameClashAction
,
945 const OUString
& rMimeType
,
947 const OUString
& rVersionComment
,
948 OUString
* pResultURL
,
949 const OUString
& rDocumentId
) const
951 Reference
< XUniversalContentBroker
> pBroker(
952 UniversalContentBroker::create( m_xImpl
->getComponentContext() ) );
954 // Execute command "globalTransfer" at UCB.
956 TransferCommandOperation eTransOp
= TransferCommandOperation();
957 OUString
sCommand( "globalTransfer" );
958 bool bCheckIn
= false;
959 switch ( eOperation
)
961 case InsertOperation::Copy
:
962 eTransOp
= TransferCommandOperation_COPY
;
965 case InsertOperation::Move
:
966 eTransOp
= TransferCommandOperation_MOVE
;
969 case InsertOperation::Checkin
:
970 eTransOp
= TransferCommandOperation_COPY
;
971 sCommand
= "checkin";
976 aCommand
.Name
= sCommand
;
977 aCommand
.Handle
= -1; // n/a
981 GlobalTransferCommandArgument2
aTransferArg(
983 rSourceContent
.getURL(), // SourceURL
984 getURL(), // TargetFolderURL,
989 aCommand
.Argument
<<= aTransferArg
;
993 CheckinArgument
aCheckinArg( bMajorVersion
, rVersionComment
,
994 rSourceContent
.getURL(), getURL(), rTitle
, rMimeType
);
995 aCommand
.Argument
<<= aCheckinArg
;
998 Any aRet
= pBroker
->execute( aCommand
, 0, m_xImpl
->getEnvironment() );
999 if ( pResultURL
!= nullptr )
1000 aRet
>>= *pResultURL
;
1004 bool Content::isFolder()
1006 bool bFolder
= false;
1007 if ( getPropertyValue("IsFolder")
1011 ucbhelper::cancelCommandExecution(
1012 makeAny( UnknownPropertyException(
1013 "Unable to retrieve value of property 'IsFolder'!",
1015 m_xImpl
->getEnvironment() );
1017 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1018 // Unreachable - cancelCommandExecution always throws an exception.
1019 // But some compilers complain...
1025 SAL_WNOUNREACHABLE_CODE_PUSH
1027 bool Content::isDocument()
1030 if ( getPropertyValue("IsDocument")
1034 ucbhelper::cancelCommandExecution(
1035 makeAny( UnknownPropertyException(
1036 "Unable to retrieve value of property 'IsDocument'!",
1038 m_xImpl
->getEnvironment() );
1040 // Unreachable - cancelCommandExecution always throws an exception,
1041 // But some compilers complain...
1045 SAL_WNOUNREACHABLE_CODE_POP
1047 void Content::lock()
1050 aCommand
.Name
= "lock";
1051 aCommand
.Handle
= -1; // n/a
1053 m_xImpl
->executeCommand( aCommand
);
1057 void Content::unlock()
1061 aCommand
.Name
= "unlock";
1062 aCommand
.Handle
= -1; // n/a
1064 m_xImpl
->executeCommand( aCommand
);
1069 // Content_Impl Implementation.
1072 Content_Impl::Content_Impl( const Reference
< XComponentContext
>& rCtx
,
1073 const Reference
< XContent
>& rContent
,
1074 const Reference
< XCommandEnvironment
>& rEnv
)
1076 m_xContent( rContent
),
1080 if ( m_xContent
.is() )
1082 m_xContentEventListener
= new ContentEventListener_Impl( *this );
1083 m_xContent
->addContentEventListener( m_xContentEventListener
);
1085 #if OSL_DEBUG_LEVEL > 0
1086 // Only done on demand in product version for performance reasons,
1087 // but a nice debug helper.
1094 void Content_Impl::reinit( const Reference
< XContent
>& xContent
)
1096 osl::MutexGuard
aGuard( m_aMutex
);
1098 m_xCommandProcessor
= nullptr;
1100 // #92581# - Don't reset m_aURL!!!
1102 if ( m_xContent
.is() )
1106 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1108 catch ( RuntimeException
const & )
1113 if ( xContent
.is() )
1115 m_xContent
= xContent
;
1116 m_xContent
->addContentEventListener( m_xContentEventListener
);
1118 #if OSL_DEBUG_LEVEL > 0
1119 // Only done on demand in product version for performance reasons,
1120 // but a nice debug helper.
1126 // We need m_xContent's URL in order to be able to create the
1127 // content object again if demanded ( --> Content_Impl::getContent() )
1130 m_xContent
= nullptr;
1136 Content_Impl::~Content_Impl()
1138 if ( m_xContent
.is() )
1142 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1144 catch ( RuntimeException
const & )
1151 void Content_Impl::disposing( const EventObject
& Source
)
1153 Reference
<XContent
> xContent
;
1156 osl::MutexGuard
aGuard( m_aMutex
);
1157 if(Source
.Source
!= m_xContent
)
1160 xContent
= m_xContent
;
1163 m_xCommandProcessor
= nullptr;
1164 m_xContent
= nullptr;
1167 if ( xContent
.is() )
1171 xContent
->removeContentEventListener( m_xContentEventListener
);
1173 catch ( RuntimeException
const & )
1180 const OUString
& Content_Impl::getURL() const
1182 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1184 osl::MutexGuard
aGuard( m_aMutex
);
1186 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1188 Reference
< XContentIdentifier
> xId
= m_xContent
->getIdentifier();
1190 m_aURL
= xId
->getContentIdentifier();
1198 Reference
< XContent
> Content_Impl::getContent()
1200 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1202 osl::MutexGuard
aGuard( m_aMutex
);
1204 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1206 Reference
< XUniversalContentBroker
> pBroker(
1207 UniversalContentBroker::create( getComponentContext() ) );
1209 OSL_ENSURE( pBroker
->queryContentProviders().getLength(),
1210 "Content Broker not configured (no providers)!" );
1212 Reference
< XContentIdentifier
> xId
1213 = pBroker
->createContentIdentifier( m_aURL
);
1215 OSL_ENSURE( xId
.is(), "No Content Identifier!" );
1221 m_xContent
= pBroker
->queryContent( xId
);
1223 catch ( IllegalIdentifierException
const & )
1227 if ( m_xContent
.is() )
1228 m_xContent
->addContentEventListener(
1229 m_xContentEventListener
);
1238 Reference
< XCommandProcessor
> Content_Impl::getCommandProcessor()
1240 if ( !m_xCommandProcessor
.is() )
1242 osl::MutexGuard
aGuard( m_aMutex
);
1244 if ( !m_xCommandProcessor
.is() )
1245 m_xCommandProcessor
.set( getContent(), UNO_QUERY
);
1248 return m_xCommandProcessor
;
1252 Any
Content_Impl::executeCommand( const Command
& rCommand
)
1254 Reference
< XCommandProcessor
> xProc
= getCommandProcessor();
1259 return xProc
->execute( rCommand
, 0, m_xEnv
);
1263 inline const Reference
< XCommandEnvironment
>&
1264 Content_Impl::getEnvironment() const
1270 inline void Content_Impl::setEnvironment(
1271 const Reference
< XCommandEnvironment
>& xNewEnv
)
1273 osl::MutexGuard
aGuard( m_aMutex
);
1278 void Content_Impl::inserted()
1280 // URL might have changed during 'insert' => recalculate in next getURL()
1281 osl::MutexGuard
aGuard( m_aMutex
);
1286 // ContentEventListener_Impl Implementation.
1289 // XInterface methods.
1291 void SAL_CALL
ContentEventListener_Impl::acquire()
1294 OWeakObject::acquire();
1297 void SAL_CALL
ContentEventListener_Impl::release()
1300 OWeakObject::release();
1303 css::uno::Any SAL_CALL
ContentEventListener_Impl::queryInterface( const css::uno::Type
& rType
)
1305 css::uno::Any aRet
= cppu::queryInterface( rType
,
1306 static_cast< XContentEventListener
* >(this),
1307 static_cast< XEventListener
* >(this)
1309 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
1312 // XContentEventListener methods.
1316 void SAL_CALL
ContentEventListener_Impl::contentEvent( const ContentEvent
& evt
)
1318 if ( evt
.Source
== m_rContent
.m_xContent
)
1320 switch ( evt
.Action
)
1322 case ContentAction::DELETED
:
1323 m_rContent
.reinit( Reference
< XContent
>() );
1326 case ContentAction::EXCHANGED
:
1327 m_rContent
.reinit( evt
.Content
);
1337 // XEventListenr methods.
1341 void SAL_CALL
ContentEventListener_Impl::disposing( const EventObject
& Source
)
1343 m_rContent
.disposing(Source
);
1346 } /* namespace ucbhelper */
1348 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */