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>
30 #include <cppuhelper/implbase.hxx>
31 #include <com/sun/star/ucb/CheckinArgument.hpp>
32 #include <com/sun/star/ucb/ContentCreationError.hpp>
33 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
34 #include <com/sun/star/ucb/XCommandInfo.hpp>
35 #include <com/sun/star/ucb/XCommandProcessor.hpp>
36 #include <com/sun/star/ucb/Command.hpp>
37 #include <com/sun/star/ucb/CommandInfo.hpp>
38 #include <com/sun/star/ucb/ContentAction.hpp>
39 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
40 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
41 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
42 #include <com/sun/star/ucb/NameClash.hpp>
43 #include <com/sun/star/ucb/OpenMode.hpp>
44 #include <com/sun/star/ucb/XContentCreator.hpp>
45 #include <com/sun/star/ucb/XContentEventListener.hpp>
46 #include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
47 #include <com/sun/star/ucb/XContentProvider.hpp>
48 #include <com/sun/star/ucb/XContentProviderManager.hpp>
49 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
50 #include <com/sun/star/ucb/SortedDynamicResultSetFactory.hpp>
51 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
52 #include <com/sun/star/ucb/XUniversalContentBroker.hpp>
53 #include <com/sun/star/beans/XPropertySetInfo.hpp>
54 #include <com/sun/star/beans/Property.hpp>
55 #include <com/sun/star/beans/PropertyValue.hpp>
56 #include <com/sun/star/sdbc/XResultSet.hpp>
57 #include <com/sun/star/sdbc/XRow.hpp>
58 #include <com/sun/star/lang/IllegalArgumentException.hpp>
59 #include <com/sun/star/beans/UnknownPropertyException.hpp>
60 #include <ucbhelper/macros.hxx>
61 #include <ucbhelper/content.hxx>
62 #include <ucbhelper/activedatasink.hxx>
63 #include <ucbhelper/activedatastreamer.hxx>
64 #include <ucbhelper/interactionrequest.hxx>
65 #include <ucbhelper/cancelcommandexecution.hxx>
67 using namespace com::sun::star::container
;
68 using namespace com::sun::star::beans
;
69 using namespace com::sun::star::io
;
70 using namespace com::sun::star::lang
;
71 using namespace com::sun::star::sdbc
;
72 using namespace com::sun::star::task
;
73 using namespace com::sun::star::ucb
;
74 using namespace com::sun::star::uno
;
79 class EmptyInputStream
: public ::cppu::WeakImplHelper
< XInputStream
>
82 virtual sal_Int32 SAL_CALL
readBytes(
83 Sequence
< sal_Int8
> & data
, sal_Int32 nBytesToRead
)
84 throw (IOException
, RuntimeException
, std::exception
) override
;
85 virtual sal_Int32 SAL_CALL
readSomeBytes(
86 Sequence
< sal_Int8
> & data
, sal_Int32 nMaxBytesToRead
)
87 throw (IOException
, RuntimeException
, std::exception
) override
;
88 virtual void SAL_CALL
skipBytes( sal_Int32 nBytesToSkip
)
89 throw (IOException
, RuntimeException
, std::exception
) override
;
90 virtual sal_Int32 SAL_CALL
available()
91 throw (IOException
, RuntimeException
, std::exception
) override
;
92 virtual void SAL_CALL
closeInput()
93 throw (IOException
, RuntimeException
, std::exception
) override
;
96 sal_Int32
EmptyInputStream::readBytes(
97 Sequence
< sal_Int8
> & data
, sal_Int32
)
98 throw (IOException
, RuntimeException
, std::exception
)
104 sal_Int32
EmptyInputStream::readSomeBytes(
105 Sequence
< sal_Int8
> & data
, sal_Int32
)
106 throw (IOException
, RuntimeException
, std::exception
)
112 void EmptyInputStream::skipBytes( sal_Int32
)
113 throw (IOException
, RuntimeException
, std::exception
)
117 sal_Int32
EmptyInputStream::available()
118 throw (IOException
, RuntimeException
, std::exception
)
123 void EmptyInputStream::closeInput()
124 throw (IOException
, RuntimeException
, std::exception
)
129 // class ContentEventListener_Impl.
132 class ContentEventListener_Impl
: public cppu::OWeakObject
,
133 public XContentEventListener
135 Content_Impl
& m_rContent
;
138 explicit ContentEventListener_Impl( Content_Impl
& rContent
)
139 : m_rContent( rContent
) {}
142 virtual css::uno::Any SAL_CALL
queryInterface( const css::uno::Type
& rType
)
143 throw( css::uno::RuntimeException
, std::exception
) override
;
144 virtual void SAL_CALL
acquire()
146 virtual void SAL_CALL
release()
149 // XContentEventListener
150 virtual void SAL_CALL
contentEvent( const ContentEvent
& evt
)
151 throw( RuntimeException
, std::exception
) override
;
153 // XEventListener ( base of XContentEventListener )
154 virtual void SAL_CALL
disposing( const EventObject
& Source
)
155 throw( RuntimeException
, std::exception
) override
;
159 // class Content_Impl.
162 class Content_Impl
: public salhelper::SimpleReferenceObject
164 friend class ContentEventListener_Impl
;
166 mutable OUString m_aURL
;
167 Reference
< XComponentContext
> m_xCtx
;
168 Reference
< XContent
> m_xContent
;
169 Reference
< XCommandProcessor
> m_xCommandProcessor
;
170 Reference
< XCommandEnvironment
> m_xEnv
;
171 Reference
< XContentEventListener
> m_xContentEventListener
;
172 mutable osl::Mutex m_aMutex
;
175 void reinit( const Reference
< XContent
>& xContent
);
176 void disposing(const EventObject
& Source
);
180 Content_Impl( const Reference
< XComponentContext
>& rCtx
,
181 const Reference
< XContent
>& rContent
,
182 const Reference
< XCommandEnvironment
>& rEnv
);
184 virtual ~Content_Impl() override
;
186 const OUString
& getURL() const;
187 Reference
< XContent
> getContent();
188 Reference
< XCommandProcessor
> getCommandProcessor();
189 Reference
< XComponentContext
> const & getComponentContext()
190 { assert(m_xCtx
.is()); return m_xCtx
; }
192 Any
executeCommand( const Command
& rCommand
);
194 inline const Reference
< XCommandEnvironment
>& getEnvironment() const;
195 inline void setEnvironment(
196 const Reference
< XCommandEnvironment
>& xNewEnv
);
205 static void ensureContentProviderForURL( const Reference
< XUniversalContentBroker
>& rBroker
,
206 const OUString
& rURL
)
207 throw ( ContentCreationException
, RuntimeException
)
209 Reference
< XContentProvider
> xProv
210 = rBroker
->queryContentProvider( rURL
);
213 throw ContentCreationException(
214 "No Content Provider available for URL: " + rURL
,
215 Reference
< XInterface
>(),
216 ContentCreationError_NO_CONTENT_PROVIDER
);
221 static Reference
< XContentIdentifier
> getContentIdentifierThrow(
222 const Reference
< XUniversalContentBroker
> & rBroker
,
223 const OUString
& rURL
)
224 throw (ContentCreationException
, RuntimeException
)
226 Reference
< XContentIdentifier
> xId
227 = rBroker
->createContentIdentifier( rURL
);
231 ensureContentProviderForURL( rBroker
, rURL
);
233 throw ContentCreationException(
234 "Unable to create Content Identifier!",
235 Reference
< XInterface
>(),
236 ContentCreationError_IDENTIFIER_CREATION_FAILED
);
242 static Reference
< XContentIdentifier
> getContentIdentifierNoThrow(
243 const Reference
< XUniversalContentBroker
> & rBroker
,
244 const OUString
& rURL
)
245 throw (RuntimeException
)
247 return rBroker
->createContentIdentifier(rURL
);
250 static Reference
< XContent
> getContentThrow(
251 const Reference
< XUniversalContentBroker
> & rBroker
,
252 const Reference
< XContentIdentifier
> & xId
)
253 throw ( ContentCreationException
, RuntimeException
)
255 Reference
< XContent
> xContent
;
259 xContent
= rBroker
->queryContent( xId
);
261 catch ( IllegalIdentifierException
const & e
)
267 if ( !xContent
.is() )
269 ensureContentProviderForURL( rBroker
, xId
->getContentIdentifier() );
271 throw ContentCreationException(
272 "Unable to create Content for <" + xId
->getContentIdentifier() + ">: " + msg
,
273 Reference
< XInterface
>(),
274 ContentCreationError_CONTENT_CREATION_FAILED
);
281 static Reference
< XContent
> getContentNoThrow(
282 const Reference
< XUniversalContentBroker
> & rBroker
,
283 const Reference
< XContentIdentifier
> & xId
)
284 throw ( RuntimeException
)
286 Reference
< XContent
> xContent
;
289 xContent
= rBroker
->queryContent( xId
);
291 catch ( IllegalIdentifierException
const & e
)
293 SAL_WARN("ucbhelper", "getContentNoThrow: exception: " << e
.Message
);
300 // Content Implementation.
304 : m_xImpl( new Content_Impl
)
309 Content::Content( const OUString
& rURL
,
310 const Reference
< XCommandEnvironment
>& rEnv
,
311 const Reference
< XComponentContext
>& rCtx
)
312 throw ( ContentCreationException
, RuntimeException
)
314 Reference
< XUniversalContentBroker
> pBroker(
315 UniversalContentBroker::create( rCtx
) );
317 Reference
< XContentIdentifier
> xId
318 = getContentIdentifierThrow(pBroker
, rURL
);
320 Reference
< XContent
> xContent
= getContentThrow(pBroker
, xId
);
322 m_xImpl
= new Content_Impl( rCtx
, xContent
, rEnv
);
326 Content::Content( const Reference
< XContent
>& rContent
,
327 const Reference
< XCommandEnvironment
>& rEnv
,
328 const Reference
< XComponentContext
>& rCtx
)
329 throw ( ContentCreationException
, RuntimeException
)
331 m_xImpl
= new Content_Impl( rCtx
, rContent
, rEnv
);
335 Content::Content( const Content
& rOther
)
337 m_xImpl
= rOther
.m_xImpl
;
340 Content::Content( Content
&& rOther
)
342 m_xImpl
= std::move(rOther
.m_xImpl
);
346 bool Content::create( const OUString
& rURL
,
347 const Reference
< XCommandEnvironment
>& rEnv
,
348 const Reference
< XComponentContext
>& rCtx
,
351 Reference
< XUniversalContentBroker
> pBroker(
352 UniversalContentBroker::create( rCtx
) );
354 Reference
< XContentIdentifier
> xId
355 = getContentIdentifierNoThrow(pBroker
, rURL
);
359 Reference
< XContent
> xContent
= getContentNoThrow(pBroker
, xId
);
360 if ( !xContent
.is() )
364 = new Content_Impl( rCtx
, xContent
, rEnv
);
375 Content
& Content::operator=( const Content
& rOther
)
377 m_xImpl
= rOther
.m_xImpl
;
381 Content
& Content::operator=( Content
&& rOther
)
383 m_xImpl
= std::move(rOther
.m_xImpl
);
387 Reference
< XContent
> Content::get() const
389 return m_xImpl
->getContent();
393 const OUString
& Content::getURL() const
395 return m_xImpl
->getURL();
399 const Reference
< XCommandEnvironment
>& Content::getCommandEnvironment() const
401 return m_xImpl
->getEnvironment();
405 void Content::setCommandEnvironment(
406 const Reference
< XCommandEnvironment
>& xNewEnv
)
408 m_xImpl
->setEnvironment( xNewEnv
);
412 Reference
< XCommandInfo
> Content::getCommands()
413 throw( CommandAbortedException
, RuntimeException
, Exception
)
416 aCommand
.Name
= "getCommandInfo";
417 aCommand
.Handle
= -1; // n/a
418 aCommand
.Argument
= Any();
420 Any aResult
= m_xImpl
->executeCommand( aCommand
);
422 Reference
< XCommandInfo
> xInfo
;
428 Reference
< XPropertySetInfo
> Content::getProperties()
429 throw( CommandAbortedException
, RuntimeException
, Exception
)
432 aCommand
.Name
= "getPropertySetInfo";
433 aCommand
.Handle
= -1; // n/a
434 aCommand
.Argument
= Any();
436 Any aResult
= m_xImpl
->executeCommand( aCommand
);
438 Reference
< XPropertySetInfo
> xInfo
;
444 Any
Content::getPropertyValue( const OUString
& rPropertyName
)
445 throw( CommandAbortedException
, RuntimeException
, Exception
)
447 Sequence
<OUString
> aNames
{ rPropertyName
};
449 Sequence
< Any
> aRet
= getPropertyValues( aNames
);
450 return aRet
.getConstArray()[ 0 ];
454 Any
Content::setPropertyValue( const OUString
& rName
,
456 throw( CommandAbortedException
, RuntimeException
, Exception
)
458 Sequence
<OUString
> aNames
{ rName
};
460 Sequence
< Any
> aValues( 1 );
461 aValues
.getArray()[ 0 ] = rValue
;
463 Sequence
< Any
> aErrors
= setPropertyValues( aNames
, aValues
);
464 return aErrors
.getConstArray()[ 0 ];
468 Sequence
< Any
> Content::getPropertyValues(
469 const Sequence
< OUString
>& rPropertyNames
)
470 throw( CommandAbortedException
, RuntimeException
, Exception
)
472 Reference
< XRow
> xRow
= getPropertyValuesInterface( rPropertyNames
);
474 sal_Int32 nCount
= rPropertyNames
.getLength();
475 Sequence
< Any
> aValues( nCount
);
479 Any
* pValues
= aValues
.getArray();
481 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
482 pValues
[ n
] = xRow
->getObject( n
+ 1, Reference
< XNameAccess
>() );
489 Reference
< XRow
> Content::getPropertyValuesInterface(
490 const Sequence
< OUString
>& rPropertyNames
)
491 throw( CommandAbortedException
, RuntimeException
, Exception
)
493 sal_Int32 nCount
= rPropertyNames
.getLength();
494 Sequence
< Property
> aProps( nCount
);
495 Property
* pProps
= aProps
.getArray();
497 const OUString
* pNames
= rPropertyNames
.getConstArray();
499 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
501 Property
& rProp
= pProps
[ n
];
503 rProp
.Name
= pNames
[ n
];
504 rProp
.Handle
= -1; // n/a
506 // rProp.Attributes = ;
510 aCommand
.Name
= "getPropertyValues";
511 aCommand
.Handle
= -1; // n/a
512 aCommand
.Argument
<<= aProps
;
514 Any aResult
= m_xImpl
->executeCommand( aCommand
);
516 Reference
< XRow
> xRow
;
522 Sequence
< Any
> Content::setPropertyValues(
523 const Sequence
< OUString
>& rPropertyNames
,
524 const Sequence
< Any
>& rValues
)
525 throw( CommandAbortedException
, RuntimeException
, Exception
)
527 if ( rPropertyNames
.getLength() != rValues
.getLength() )
529 ucbhelper::cancelCommandExecution(
530 makeAny( IllegalArgumentException(
532 "Length of property names sequence and value "
533 "sequence are unequal!" ),
536 m_xImpl
->getEnvironment() );
540 sal_Int32 nCount
= rValues
.getLength();
541 Sequence
< PropertyValue
> aProps( nCount
);
542 PropertyValue
* pProps
= aProps
.getArray();
544 const OUString
* pNames
= rPropertyNames
.getConstArray();
545 const Any
* pValues
= rValues
.getConstArray();
547 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
549 PropertyValue
& rProp
= pProps
[ n
];
551 rProp
.Name
= pNames
[ n
];
552 rProp
.Handle
= -1; // n/a
553 rProp
.Value
= pValues
[ n
];
558 aCommand
.Name
= "setPropertyValues";
559 aCommand
.Handle
= -1; // n/a
560 aCommand
.Argument
<<= aProps
;
562 Any aResult
= m_xImpl
->executeCommand( aCommand
);
564 Sequence
< Any
> aErrors
;
570 Any
Content::executeCommand( const OUString
& rCommandName
,
571 const Any
& rCommandArgument
)
572 throw( CommandAbortedException
, RuntimeException
, Exception
)
575 aCommand
.Name
= rCommandName
;
576 aCommand
.Handle
= -1; // n/a
577 aCommand
.Argument
= rCommandArgument
;
579 return m_xImpl
->executeCommand( aCommand
);
583 Any
Content::createCursorAny( const Sequence
< OUString
>& rPropertyNames
,
584 ResultSetInclude eMode
)
585 throw( CommandAbortedException
, RuntimeException
, Exception
)
587 sal_Int32 nCount
= rPropertyNames
.getLength();
588 Sequence
< Property
> aProps( nCount
);
589 Property
* pProps
= aProps
.getArray();
590 const OUString
* pNames
= rPropertyNames
.getConstArray();
591 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
593 Property
& rProp
= pProps
[ n
];
594 rProp
.Name
= pNames
[ n
];
595 rProp
.Handle
= -1; // n/a
598 OpenCommandArgument2 aArg
;
599 aArg
.Mode
= ( eMode
== INCLUDE_FOLDERS_ONLY
)
601 : ( eMode
== INCLUDE_DOCUMENTS_ONLY
)
602 ? OpenMode::DOCUMENTS
: OpenMode::ALL
;
603 aArg
.Priority
= 0; // unused
604 aArg
.Sink
.clear(); // unused
605 aArg
.Properties
= aProps
;
608 aCommand
.Name
= "open";
609 aCommand
.Handle
= -1; // n/a
610 aCommand
.Argument
<<= aArg
;
612 return m_xImpl
->executeCommand( aCommand
);
616 Reference
< XResultSet
> Content::createCursor(
617 const Sequence
< OUString
>& rPropertyNames
,
618 ResultSetInclude eMode
)
619 throw( CommandAbortedException
, RuntimeException
, Exception
)
621 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
623 Reference
< XDynamicResultSet
> xDynSet
;
624 Reference
< XResultSet
> aResult
;
626 aCursorAny
>>= xDynSet
;
628 aResult
= xDynSet
->getStaticResultSet();
630 OSL_ENSURE( aResult
.is(), "Content::createCursor - no cursor!" );
634 // Former, the open command directly returned a XResultSet.
635 aCursorAny
>>= aResult
;
637 OSL_ENSURE( !aResult
.is(),
638 "Content::createCursor - open-Command must "
639 "return a Reference< XDynnamicResultSet >!" );
646 Reference
< XDynamicResultSet
> Content::createDynamicCursor(
647 const Sequence
< OUString
>& rPropertyNames
,
648 ResultSetInclude eMode
)
649 throw( CommandAbortedException
, RuntimeException
, Exception
)
651 Reference
< XDynamicResultSet
> aResult
;
652 createCursorAny( rPropertyNames
, eMode
) >>= aResult
;
654 OSL_ENSURE( aResult
.is(), "Content::createDynamicCursor - no cursor!" );
660 Reference
< XResultSet
> Content::createSortedCursor(
661 const Sequence
< OUString
>& rPropertyNames
,
662 const Sequence
< NumberedSortingInfo
>& rSortInfo
,
663 const Reference
< XAnyCompareFactory
>& rAnyCompareFactory
,
664 ResultSetInclude eMode
)
665 throw( CommandAbortedException
, RuntimeException
, Exception
)
667 Reference
< XResultSet
> aResult
;
668 Reference
< XDynamicResultSet
> aDynSet
;
670 Any aCursorAny
= createCursorAny( rPropertyNames
, eMode
);
672 aCursorAny
>>= aDynSet
;
676 Reference
< XDynamicResultSet
> aDynResult
;
678 if( m_xImpl
->getComponentContext().is() )
680 Reference
< XSortedDynamicResultSetFactory
> aSortFactory
=
681 SortedDynamicResultSetFactory::create( m_xImpl
->getComponentContext());
683 aDynResult
= aSortFactory
->createSortedDynamicResultSet( aDynSet
,
685 rAnyCompareFactory
);
688 OSL_ENSURE( aDynResult
.is(), "Content::createSortedCursor - no sorted cursor!\n" );
690 if( aDynResult
.is() )
691 aResult
= aDynResult
->getStaticResultSet();
693 aResult
= aDynSet
->getStaticResultSet();
696 OSL_ENSURE( aResult
.is(), "Content::createSortedCursor - no cursor!" );
700 // Former, the open command directly returned a XResultSet.
701 aCursorAny
>>= aResult
;
703 OSL_ENSURE( !aResult
.is(),
704 "Content::createCursor - open-Command must "
705 "return a Reference< XDynnamicResultSet >!" );
712 Reference
< XInputStream
> Content::openStream()
713 throw( CommandAbortedException
, RuntimeException
, Exception
)
716 return Reference
< XInputStream
>();
718 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
720 OpenCommandArgument2 aArg
;
721 aArg
.Mode
= OpenMode::DOCUMENT
;
722 aArg
.Priority
= 0; // unused
724 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
727 aCommand
.Name
= "open";
728 aCommand
.Handle
= -1; // n/a
729 aCommand
.Argument
<<= aArg
;
731 m_xImpl
->executeCommand( aCommand
);
733 return xSink
->getInputStream();
737 Reference
< XInputStream
> Content::openStreamNoLock()
738 throw( CommandAbortedException
, RuntimeException
, Exception
)
741 return Reference
< XInputStream
>();
743 Reference
< XActiveDataSink
> xSink
= new ActiveDataSink
;
745 OpenCommandArgument2 aArg
;
746 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
747 aArg
.Priority
= 0; // unused
749 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
752 aCommand
.Name
= "open";
753 aCommand
.Handle
= -1; // n/a
754 aCommand
.Argument
<<= aArg
;
756 m_xImpl
->executeCommand( aCommand
);
758 return xSink
->getInputStream();
762 Reference
< XStream
> Content::openWriteableStream()
763 throw( CommandAbortedException
, RuntimeException
, Exception
)
766 return Reference
< XStream
>();
768 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
770 OpenCommandArgument2 aArg
;
771 aArg
.Mode
= OpenMode::DOCUMENT
;
772 aArg
.Priority
= 0; // unused
773 aArg
.Sink
= xStreamer
;
774 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
777 aCommand
.Name
= "open";
778 aCommand
.Handle
= -1; // n/a
779 aCommand
.Argument
<<= aArg
;
781 m_xImpl
->executeCommand( aCommand
);
783 return xStreamer
->getStream();
787 Reference
< XStream
> Content::openWriteableStreamNoLock()
788 throw( CommandAbortedException
, RuntimeException
, Exception
)
791 return Reference
< XStream
>();
793 Reference
< XActiveDataStreamer
> xStreamer
= new ActiveDataStreamer
;
795 OpenCommandArgument2 aArg
;
796 aArg
.Mode
= OpenMode::DOCUMENT_SHARE_DENY_NONE
;
797 aArg
.Priority
= 0; // unused
798 aArg
.Sink
= xStreamer
;
799 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
802 aCommand
.Name
= "open";
803 aCommand
.Handle
= -1; // n/a
804 aCommand
.Argument
<<= aArg
;
806 m_xImpl
->executeCommand( aCommand
);
808 return xStreamer
->getStream();
812 bool Content::openStream( const Reference
< XActiveDataSink
>& rSink
)
813 throw( CommandAbortedException
, RuntimeException
, Exception
)
818 OpenCommandArgument2 aArg
;
819 aArg
.Mode
= OpenMode::DOCUMENT
;
820 aArg
.Priority
= 0; // unused
822 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
825 aCommand
.Name
= "open";
826 aCommand
.Handle
= -1; // n/a
827 aCommand
.Argument
<<= aArg
;
829 m_xImpl
->executeCommand( aCommand
);
835 bool Content::openStream( const Reference
< XOutputStream
>& rStream
)
836 throw( CommandAbortedException
, RuntimeException
, Exception
)
841 OpenCommandArgument2 aArg
;
842 aArg
.Mode
= OpenMode::DOCUMENT
;
843 aArg
.Priority
= 0; // unused
845 aArg
.Properties
= Sequence
< Property
>( 0 ); // unused
848 aCommand
.Name
= "open";
849 aCommand
.Handle
= -1; // n/a
850 aCommand
.Argument
<<= aArg
;
852 m_xImpl
->executeCommand( aCommand
);
858 void Content::writeStream( const Reference
< XInputStream
>& rStream
,
859 bool bReplaceExisting
)
860 throw( CommandAbortedException
, RuntimeException
, Exception
)
862 InsertCommandArgument aArg
;
863 aArg
.Data
= rStream
.is() ? rStream
: new EmptyInputStream
;
864 aArg
.ReplaceExisting
= bReplaceExisting
;
867 aCommand
.Name
= "insert";
868 aCommand
.Handle
= -1; // n/a
869 aCommand
.Argument
<<= aArg
;
871 m_xImpl
->executeCommand( aCommand
);
877 Sequence
< ContentInfo
> Content::queryCreatableContentsInfo()
878 throw( CommandAbortedException
, RuntimeException
, Exception
)
880 // First, try it using "CreatableContentsInfo" property -> the "new" way.
881 Sequence
< ContentInfo
> aInfo
;
882 if ( getPropertyValue(
883 "CreatableContentsInfo" )
887 // Second, try it using XContentCreator interface -> the "old" way (not
888 // providing the chance to supply an XCommandEnvironment.
889 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
891 aInfo
= xCreator
->queryCreatableContentsInfo();
897 bool Content::insertNewContent( const OUString
& rContentType
,
898 const Sequence
< OUString
>&
900 const Sequence
< Any
>& rPropertyValues
,
901 Content
& rNewContent
)
902 throw( CommandAbortedException
, RuntimeException
, Exception
)
904 return insertNewContent( rContentType
,
907 new EmptyInputStream
,
912 bool Content::insertNewContent( const OUString
& rContentType
,
913 const Sequence
< OUString
>&
915 const Sequence
< Any
>& rPropertyValues
,
916 const Reference
< XInputStream
>& rData
,
917 Content
& rNewContent
)
918 throw( CommandAbortedException
, RuntimeException
, Exception
)
920 if ( rContentType
.isEmpty() )
923 // First, try it using "createNewContent" command -> the "new" way.
925 aInfo
.Type
= rContentType
;
926 aInfo
.Attributes
= 0;
929 aCommand
.Name
= "createNewContent";
930 aCommand
.Handle
= -1; // n/a
931 aCommand
.Argument
<<= aInfo
;
933 Reference
< XContent
> xNew
;
936 m_xImpl
->executeCommand( aCommand
) >>= xNew
;
938 catch ( RuntimeException
const & )
942 catch ( Exception
const & )
948 // Second, try it using XContentCreator interface -> the "old"
949 // way (not providing the chance to supply an XCommandEnvironment.
950 Reference
< XContentCreator
> xCreator( m_xImpl
->getContent(), UNO_QUERY
);
952 if ( !xCreator
.is() )
955 xNew
= xCreator
->createNewContent( aInfo
);
962 xNew
, m_xImpl
->getEnvironment(), m_xImpl
->getComponentContext() );
963 aNewContent
.setPropertyValues( rPropertyNames
, rPropertyValues
);
964 aNewContent
.executeCommand( "insert",
966 InsertCommandArgument(
967 rData
.is() ? rData
: new EmptyInputStream
,
968 false /* ReplaceExisting */ ) ) );
969 aNewContent
.m_xImpl
->inserted();
971 rNewContent
= aNewContent
;
976 bool Content::transferContent( const Content
& rSourceContent
,
977 InsertOperation eOperation
,
978 const OUString
& rTitle
,
979 const sal_Int32 nNameClashAction
,
980 const OUString
& rMimeType
,
982 const OUString
& rVersionComment
,
983 OUString
* pResultURL
,
984 const OUString
& rDocumentId
)
985 throw( CommandAbortedException
, RuntimeException
, Exception
)
987 Reference
< XUniversalContentBroker
> pBroker(
988 UniversalContentBroker::create( m_xImpl
->getComponentContext() ) );
990 // Execute command "globalTransfer" at UCB.
992 TransferCommandOperation eTransOp
= TransferCommandOperation();
993 OUString
sCommand( "globalTransfer" );
994 bool bCheckIn
= false;
995 switch ( eOperation
)
997 case InsertOperation_COPY
:
998 eTransOp
= TransferCommandOperation_COPY
;
1001 case InsertOperation_MOVE
:
1002 eTransOp
= TransferCommandOperation_MOVE
;
1005 case InsertOperation_LINK
:
1006 eTransOp
= TransferCommandOperation_LINK
;
1009 case InsertOperation_CHECKIN
:
1010 eTransOp
= TransferCommandOperation_COPY
;
1011 sCommand
= "checkin";
1016 aCommand
.Name
= sCommand
;
1017 aCommand
.Handle
= -1; // n/a
1021 GlobalTransferCommandArgument2
aTransferArg(
1023 rSourceContent
.getURL(), // SourceURL
1024 getURL(), // TargetFolderURL,
1029 aCommand
.Argument
<<= aTransferArg
;
1033 CheckinArgument
aCheckinArg( bMajorVersion
, rVersionComment
,
1034 rSourceContent
.getURL(), getURL(), rTitle
, rMimeType
);
1035 aCommand
.Argument
<<= aCheckinArg
;
1038 Any aRet
= pBroker
->execute( aCommand
, 0, m_xImpl
->getEnvironment() );
1039 if ( pResultURL
!= nullptr )
1040 aRet
>>= *pResultURL
;
1045 bool Content::isFolder()
1046 throw( CommandAbortedException
, RuntimeException
, Exception
)
1048 bool bFolder
= false;
1049 if ( getPropertyValue("IsFolder")
1053 ucbhelper::cancelCommandExecution(
1054 makeAny( UnknownPropertyException(
1056 "Unable to retrieve value of property 'IsFolder'!" ),
1058 m_xImpl
->getEnvironment() );
1060 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1061 // Unreachable - cancelCommandExecution always throws an exception.
1062 // But some compilers complain...
1068 SAL_WNOUNREACHABLE_CODE_PUSH
1070 bool Content::isDocument()
1071 throw( CommandAbortedException
, RuntimeException
, Exception
)
1074 if ( getPropertyValue("IsDocument")
1078 ucbhelper::cancelCommandExecution(
1079 makeAny( UnknownPropertyException(
1081 "Unable to retrieve value of property 'IsDocument'!" ),
1083 m_xImpl
->getEnvironment() );
1085 // Unreachable - cancelCommandExecution always throws an exception,
1086 // But some compilers complain...
1090 SAL_WNOUNREACHABLE_CODE_POP
1092 void Content::lock()
1093 throw( CommandAbortedException
, RuntimeException
, Exception
)
1096 aCommand
.Name
= "lock";
1097 aCommand
.Handle
= -1; // n/a
1099 m_xImpl
->executeCommand( aCommand
);
1103 void Content::unlock()
1104 throw( CommandAbortedException
, RuntimeException
, Exception
)
1108 aCommand
.Name
= "unlock";
1109 aCommand
.Handle
= -1; // n/a
1111 m_xImpl
->executeCommand( aCommand
);
1116 // Content_Impl Implementation.
1119 Content_Impl::Content_Impl( const Reference
< XComponentContext
>& rCtx
,
1120 const Reference
< XContent
>& rContent
,
1121 const Reference
< XCommandEnvironment
>& rEnv
)
1123 m_xContent( rContent
),
1127 if ( m_xContent
.is() )
1129 m_xContentEventListener
= new ContentEventListener_Impl( *this );
1130 m_xContent
->addContentEventListener( m_xContentEventListener
);
1132 #if OSL_DEBUG_LEVEL > 0
1133 // Only done on demand in product version for performance reasons,
1134 // but a nice debug helper.
1141 void Content_Impl::reinit( const Reference
< XContent
>& xContent
)
1143 osl::MutexGuard
aGuard( m_aMutex
);
1145 m_xCommandProcessor
= nullptr;
1147 // #92581# - Don't reset m_aURL!!!
1149 if ( m_xContent
.is() )
1153 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1155 catch ( RuntimeException
const & )
1160 if ( xContent
.is() )
1162 m_xContent
= xContent
;
1163 m_xContent
->addContentEventListener( m_xContentEventListener
);
1165 #if OSL_DEBUG_LEVEL > 0
1166 // Only done on demand in product version for performance reasons,
1167 // but a nice debug helper.
1173 // We need m_xContent's URL in order to be able to create the
1174 // content object again if demanded ( --> Content_Impl::getContent() )
1177 m_xContent
= nullptr;
1183 Content_Impl::~Content_Impl()
1185 if ( m_xContent
.is() )
1189 m_xContent
->removeContentEventListener( m_xContentEventListener
);
1191 catch ( RuntimeException
const & )
1198 void Content_Impl::disposing( const EventObject
& Source
)
1200 Reference
<XContent
> xContent
;
1203 osl::MutexGuard
aGuard( m_aMutex
);
1204 if(Source
.Source
!= m_xContent
)
1207 xContent
= m_xContent
;
1210 m_xCommandProcessor
= nullptr;
1211 m_xContent
= nullptr;
1214 if ( xContent
.is() )
1218 xContent
->removeContentEventListener( m_xContentEventListener
);
1220 catch ( RuntimeException
const & )
1227 const OUString
& Content_Impl::getURL() const
1229 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1231 osl::MutexGuard
aGuard( m_aMutex
);
1233 if ( m_aURL
.isEmpty() && m_xContent
.is() )
1235 Reference
< XContentIdentifier
> xId
= m_xContent
->getIdentifier();
1237 m_aURL
= xId
->getContentIdentifier();
1245 Reference
< XContent
> Content_Impl::getContent()
1247 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1249 osl::MutexGuard
aGuard( m_aMutex
);
1251 if ( !m_xContent
.is() && !m_aURL
.isEmpty() )
1253 Reference
< XUniversalContentBroker
> pBroker(
1254 UniversalContentBroker::create( getComponentContext() ) );
1256 OSL_ENSURE( pBroker
->queryContentProviders().getLength(),
1257 "Content Broker not configured (no providers)!" );
1259 Reference
< XContentIdentifier
> xId
1260 = pBroker
->createContentIdentifier( m_aURL
);
1262 OSL_ENSURE( xId
.is(), "No Content Identifier!" );
1268 m_xContent
= pBroker
->queryContent( xId
);
1270 catch ( IllegalIdentifierException
const & )
1274 if ( m_xContent
.is() )
1275 m_xContent
->addContentEventListener(
1276 m_xContentEventListener
);
1285 Reference
< XCommandProcessor
> Content_Impl::getCommandProcessor()
1287 if ( !m_xCommandProcessor
.is() )
1289 osl::MutexGuard
aGuard( m_aMutex
);
1291 if ( !m_xCommandProcessor
.is() )
1292 m_xCommandProcessor
.set( getContent(), UNO_QUERY
);
1295 return m_xCommandProcessor
;
1299 Any
Content_Impl::executeCommand( const Command
& rCommand
)
1301 Reference
< XCommandProcessor
> xProc
= getCommandProcessor();
1306 return xProc
->execute( rCommand
, 0, m_xEnv
);
1310 inline const Reference
< XCommandEnvironment
>&
1311 Content_Impl::getEnvironment() const
1317 inline void Content_Impl::setEnvironment(
1318 const Reference
< XCommandEnvironment
>& xNewEnv
)
1320 osl::MutexGuard
aGuard( m_aMutex
);
1325 void Content_Impl::inserted()
1327 // URL might have changed during 'insert' => recalculate in next getURL()
1328 osl::MutexGuard
aGuard( m_aMutex
);
1333 // ContentEventListener_Impl Implementation.
1336 // XInterface methods.
1338 void SAL_CALL
ContentEventListener_Impl::acquire()
1341 OWeakObject::acquire();
1344 void SAL_CALL
ContentEventListener_Impl::release()
1347 OWeakObject::release();
1350 css::uno::Any SAL_CALL
ContentEventListener_Impl::queryInterface( const css::uno::Type
& rType
)
1351 throw( css::uno::RuntimeException
, std::exception
)
1353 css::uno::Any aRet
= cppu::queryInterface( rType
,
1354 (static_cast< XContentEventListener
* >(this)),
1355 (static_cast< XEventListener
* >(this))
1357 return aRet
.hasValue() ? aRet
: OWeakObject::queryInterface( rType
);
1360 // XContentEventListener methods.
1364 void SAL_CALL
ContentEventListener_Impl::contentEvent( const ContentEvent
& evt
)
1365 throw( RuntimeException
, std::exception
)
1367 if ( evt
.Source
== m_rContent
.m_xContent
)
1369 switch ( evt
.Action
)
1371 case ContentAction::DELETED
:
1372 m_rContent
.reinit( Reference
< XContent
>() );
1375 case ContentAction::EXCHANGED
:
1376 m_rContent
.reinit( evt
.Content
);
1386 // XEventListenr methods.
1390 void SAL_CALL
ContentEventListener_Impl::disposing( const EventObject
& Source
)
1391 throw( RuntimeException
, std::exception
)
1393 m_rContent
.disposing(Source
);
1396 } /* namespace ucbhelper */
1398 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */