lok: vcl: fix multiple floatwin removal case more robustly.
[LibreOffice.git] / ucbhelper / source / client / content.cxx
blob3308ac3b892e0017218880d48ef40f355eefa5db
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <cassert>
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;
79 namespace ucbhelper
82 class EmptyInputStream : public ::cppu::WeakImplHelper< XInputStream >
84 public:
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 )
97 data.realloc( 0 );
98 return 0;
101 sal_Int32 EmptyInputStream::readSomeBytes(
102 Sequence< sal_Int8 > & data, sal_Int32 )
104 data.realloc( 0 );
105 return 0;
108 void EmptyInputStream::skipBytes( sal_Int32 )
112 sal_Int32 EmptyInputStream::available()
114 return 0;
117 void EmptyInputStream::closeInput()
122 // class ContentEventListener_Impl.
125 class ContentEventListener_Impl : public cppu::OWeakObject,
126 public XContentEventListener
128 Content_Impl& m_rContent;
130 public:
131 explicit ContentEventListener_Impl( Content_Impl& rContent )
132 : m_rContent( rContent ) {}
134 // XInterface
135 virtual css::uno::Any SAL_CALL queryInterface( const css::uno::Type & rType ) override;
136 virtual void SAL_CALL acquire()
137 throw() override;
138 virtual void SAL_CALL release()
139 throw() override;
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;
164 private:
165 void reinit( const Reference< XContent >& xContent );
166 void disposing(const EventObject& Source);
168 public:
169 Content_Impl() {};
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 );
188 void inserted();
192 // Helpers.
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 );
201 if ( !xProv.is() )
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 );
219 if (!xId.is())
221 ensureContentProviderForURL( rBroker, rURL );
223 throw ContentCreationException(
224 "Unable to create Content Identifier!",
225 Reference< XInterface >(),
226 ContentCreationError_IDENTIFIER_CREATION_FAILED );
229 return xId;
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;
247 OUString msg;
250 xContent = rBroker->queryContent( xId );
252 catch ( IllegalIdentifierException const & e )
254 msg = e.Message;
255 // handled below.
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 );
268 return xContent;
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);
286 return xContent;
290 // Content Implementation.
293 Content::Content()
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);
333 // static
334 bool Content::create( const OUString& rURL,
335 const Reference< XCommandEnvironment >& rEnv,
336 const Reference< XComponentContext >& rCtx,
337 Content& rContent )
339 Reference< XUniversalContentBroker > pBroker(
340 UniversalContentBroker::create( rCtx ) );
342 Reference< XContentIdentifier > xId
343 = getContentIdentifierNoThrow(pBroker, rURL);
344 if ( !xId.is() )
345 return false;
347 Reference< XContent > xContent = getContentNoThrow(pBroker, xId);
348 if ( !xContent.is() )
349 return false;
351 rContent.m_xImpl
352 = new Content_Impl( rCtx, xContent, rEnv );
354 return true;
358 Content::~Content()
363 Content& Content::operator=( const Content& rOther )
365 m_xImpl = rOther.m_xImpl;
366 return *this;
369 Content& Content::operator=( Content&& rOther )
371 m_xImpl = std::move(rOther.m_xImpl);
372 return *this;
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()
402 Command aCommand;
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;
410 aResult >>= xInfo;
411 return xInfo;
415 Reference< XPropertySetInfo > Content::getProperties()
417 Command aCommand;
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;
425 aResult >>= xInfo;
426 return 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,
440 const Any& rValue )
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 );
460 if ( xRow.is() )
462 Any* pValues = aValues.getArray();
464 for ( sal_Int32 n = 0; n < nCount; ++n )
465 pValues[ n ] = xRow->getObject( n + 1, Reference< XNameAccess >() );
468 return aValues;
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
487 // rProp.Type =
488 // rProp.Attributes = ;
491 Command aCommand;
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;
499 aResult >>= xRow;
500 return 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!",
514 get(),
515 -1 ) ),
516 m_xImpl->getEnvironment() );
517 // Unreachable
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 ];
534 // rProp.State = ;
537 Command aCommand;
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;
545 aResult >>= aErrors;
546 return aErrors;
550 Any Content::executeCommand( const OUString& rCommandName,
551 const Any& rCommandArgument )
553 Command aCommand;
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 )
578 ? OpenMode::FOLDERS
579 : ( eMode == INCLUDE_DOCUMENTS_ONLY )
580 ? OpenMode::DOCUMENTS : OpenMode::ALL;
581 aArg.Priority = 0; // unused
582 aArg.Sink.clear(); // unused
583 aArg.Properties = aProps;
585 Command aCommand;
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;
604 if ( xDynSet.is() )
605 aResult = xDynSet->getStaticResultSet();
607 OSL_ENSURE( aResult.is(), "Content::createCursor - no cursor!" );
609 if ( !aResult.is() )
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 >!" );
619 return aResult;
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!" );
632 return aResult;
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;
649 if( aDynSet.is() )
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,
659 rSortInfo,
660 rAnyCompareFactory );
663 OSL_ENSURE( aDynResult.is(), "Content::createSortedCursor - no sorted cursor!" );
665 if( aDynResult.is() )
666 aResult = aDynResult->getStaticResultSet();
667 else
668 aResult = aDynSet->getStaticResultSet();
671 OSL_ENSURE( aResult.is(), "Content::createSortedCursor - no cursor!" );
673 if ( !aResult.is() )
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 >!" );
683 return aResult;
687 Reference< XInputStream > Content::openStream()
689 if ( !isDocument() )
690 return Reference< XInputStream >();
692 Reference< XActiveDataSink > xSink = new ActiveDataSink;
694 OpenCommandArgument2 aArg;
695 aArg.Mode = OpenMode::DOCUMENT;
696 aArg.Priority = 0; // unused
697 aArg.Sink = xSink;
698 aArg.Properties = Sequence< Property >( 0 ); // unused
700 Command aCommand;
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()
713 if ( !isDocument() )
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
721 aArg.Sink = xSink;
722 aArg.Properties = Sequence< Property >( 0 ); // unused
724 Command aCommand;
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()
737 if ( !isDocument() )
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
748 Command aCommand;
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()
761 if ( !isDocument() )
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
772 Command aCommand;
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 )
785 if ( !isDocument() )
786 return false;
788 OpenCommandArgument2 aArg;
789 aArg.Mode = OpenMode::DOCUMENT;
790 aArg.Priority = 0; // unused
791 aArg.Sink = rSink;
792 aArg.Properties = Sequence< Property >( 0 ); // unused
794 Command aCommand;
795 aCommand.Name = "open";
796 aCommand.Handle = -1; // n/a
797 aCommand.Argument <<= aArg;
799 m_xImpl->executeCommand( aCommand );
801 return true;
805 bool Content::openStream( const Reference< XOutputStream >& rStream )
807 if ( !isDocument() )
808 return false;
810 OpenCommandArgument2 aArg;
811 aArg.Mode = OpenMode::DOCUMENT;
812 aArg.Priority = 0; // unused
813 aArg.Sink = rStream;
814 aArg.Properties = Sequence< Property >( 0 ); // unused
816 Command aCommand;
817 aCommand.Name = "open";
818 aCommand.Handle = -1; // n/a
819 aCommand.Argument <<= aArg;
821 m_xImpl->executeCommand( aCommand );
823 return true;
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;
834 Command aCommand;
835 aCommand.Name = "insert";
836 aCommand.Handle = -1; // n/a
837 aCommand.Argument <<= aArg;
839 m_xImpl->executeCommand( aCommand );
841 m_xImpl->inserted();
845 Sequence< ContentInfo > Content::queryCreatableContentsInfo()
847 // First, try it using "CreatableContentsInfo" property -> the "new" way.
848 Sequence< ContentInfo > aInfo;
849 if ( getPropertyValue(
850 "CreatableContentsInfo" )
851 >>= aInfo )
852 return aInfo;
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 );
857 if ( xCreator.is() )
858 aInfo = xCreator->queryCreatableContentsInfo();
860 return aInfo;
864 bool Content::insertNewContent( const OUString& rContentType,
865 const Sequence< OUString >&
866 rPropertyNames,
867 const Sequence< Any >& rPropertyValues,
868 Content& rNewContent )
870 return insertNewContent( rContentType,
871 rPropertyNames,
872 rPropertyValues,
873 new EmptyInputStream,
874 rNewContent );
878 bool Content::insertNewContent( const OUString& rContentType,
879 const Sequence< OUString >&
880 rPropertyNames,
881 const Sequence< Any >& rPropertyValues,
882 const Reference< XInputStream >& rData,
883 Content& rNewContent )
885 if ( rContentType.isEmpty() )
886 return false;
888 // First, try it using "createNewContent" command -> the "new" way.
889 ContentInfo aInfo;
890 aInfo.Type = rContentType;
891 aInfo.Attributes = 0;
893 Command aCommand;
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 & )
905 throw;
907 catch ( Exception const & )
911 if ( !xNew.is() )
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() )
918 return false;
920 xNew = xCreator->createNewContent( aInfo );
922 if ( !xNew.is() )
923 return false;
926 Content aNewContent(
927 xNew, m_xImpl->getEnvironment(), m_xImpl->getComponentContext() );
928 aNewContent.setPropertyValues( rPropertyNames, rPropertyValues );
929 aNewContent.executeCommand( "insert",
930 makeAny(
931 InsertCommandArgument(
932 rData.is() ? rData : new EmptyInputStream,
933 false /* ReplaceExisting */ ) ) );
934 aNewContent.m_xImpl->inserted();
936 rNewContent = aNewContent;
937 return true;
941 void Content::transferContent( const Content& rSourceContent,
942 InsertOperation eOperation,
943 const OUString & rTitle,
944 const sal_Int32 nNameClashAction,
945 const OUString & rMimeType,
946 bool bMajorVersion,
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;
963 break;
965 case InsertOperation::Move:
966 eTransOp = TransferCommandOperation_MOVE;
967 break;
969 case InsertOperation::Checkin:
970 eTransOp = TransferCommandOperation_COPY;
971 sCommand = "checkin";
972 bCheckIn = true;
973 break;
975 Command aCommand;
976 aCommand.Name = sCommand;
977 aCommand.Handle = -1; // n/a
979 if ( !bCheckIn )
981 GlobalTransferCommandArgument2 aTransferArg(
982 eTransOp,
983 rSourceContent.getURL(), // SourceURL
984 getURL(), // TargetFolderURL,
985 rTitle,
986 nNameClashAction,
987 rMimeType,
988 rDocumentId );
989 aCommand.Argument <<= aTransferArg;
991 else
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")
1008 >>= bFolder )
1009 return bFolder;
1011 ucbhelper::cancelCommandExecution(
1012 makeAny( UnknownPropertyException(
1013 "Unable to retrieve value of property 'IsFolder'!",
1014 get() ) ),
1015 m_xImpl->getEnvironment() );
1017 #if !(defined(_MSC_VER) && defined(ENABLE_LTO))
1018 // Unreachable - cancelCommandExecution always throws an exception.
1019 // But some compilers complain...
1020 return false;
1021 #endif
1025 SAL_WNOUNREACHABLE_CODE_PUSH
1027 bool Content::isDocument()
1029 bool bDoc = false;
1030 if ( getPropertyValue("IsDocument")
1031 >>= bDoc )
1032 return bDoc;
1034 ucbhelper::cancelCommandExecution(
1035 makeAny( UnknownPropertyException(
1036 "Unable to retrieve value of property 'IsDocument'!",
1037 get() ) ),
1038 m_xImpl->getEnvironment() );
1040 // Unreachable - cancelCommandExecution always throws an exception,
1041 // But some compilers complain...
1042 return false;
1045 SAL_WNOUNREACHABLE_CODE_POP
1047 void Content::lock()
1049 Command aCommand;
1050 aCommand.Name = "lock";
1051 aCommand.Handle = -1; // n/a
1053 m_xImpl->executeCommand( aCommand );
1057 void Content::unlock()
1060 Command aCommand;
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 )
1075 : m_xCtx( rCtx ),
1076 m_xContent( rContent ),
1077 m_xEnv( rEnv )
1079 assert(rCtx.is());
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.
1088 getURL();
1089 #endif
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.
1121 getURL();
1122 #endif
1124 else
1126 // We need m_xContent's URL in order to be able to create the
1127 // content object again if demanded ( --> Content_Impl::getContent() )
1128 getURL();
1130 m_xContent = nullptr;
1135 // virtual
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)
1158 return;
1160 xContent = m_xContent;
1162 m_aURL.clear();
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();
1189 if ( xId.is() )
1190 m_aURL = xId->getContentIdentifier();
1194 return m_aURL;
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!" );
1217 if ( xId.is() )
1221 m_xContent = pBroker->queryContent( xId );
1223 catch ( IllegalIdentifierException const & )
1227 if ( m_xContent.is() )
1228 m_xContent->addContentEventListener(
1229 m_xContentEventListener );
1234 return m_xContent;
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();
1255 if ( !xProc.is() )
1256 return Any();
1258 // Execute command
1259 return xProc->execute( rCommand, 0, m_xEnv );
1263 inline const Reference< XCommandEnvironment >&
1264 Content_Impl::getEnvironment() const
1266 return m_xEnv;
1270 inline void Content_Impl::setEnvironment(
1271 const Reference< XCommandEnvironment >& xNewEnv )
1273 osl::MutexGuard aGuard( m_aMutex );
1274 m_xEnv = xNewEnv;
1278 void Content_Impl::inserted()
1280 // URL might have changed during 'insert' => recalculate in next getURL()
1281 osl::MutexGuard aGuard( m_aMutex );
1282 m_aURL.clear();
1286 // ContentEventListener_Impl Implementation.
1289 // XInterface methods.
1291 void SAL_CALL ContentEventListener_Impl::acquire()
1292 throw()
1294 OWeakObject::acquire();
1297 void SAL_CALL ContentEventListener_Impl::release()
1298 throw()
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.
1315 // virtual
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 >() );
1324 break;
1326 case ContentAction::EXCHANGED:
1327 m_rContent.reinit( evt.Content );
1328 break;
1330 default:
1331 break;
1337 // XEventListenr methods.
1340 // virtual
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: */