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 .
21 /**************************************************************************
23 **************************************************************************
25 *************************************************************************/
26 #include <osl/diagnose.h>
27 #include <comphelper/processfactory.hxx>
28 #include <cppuhelper/implbase1.hxx>
29 #include <cppuhelper/exc_hlp.hxx>
30 #include <rtl/ustring.h>
31 #include <rtl/ustring.hxx>
32 #include <com/sun/star/uno/XInterface.hpp>
33 #include <com/sun/star/beans/PropertyState.hpp>
34 #include <com/sun/star/beans/PropertyValue.hpp>
35 #include <com/sun/star/container/XChild.hpp>
36 #include <com/sun/star/beans/XPropertySetInfo.hpp>
37 #include <com/sun/star/io/Pipe.hpp>
38 #include <com/sun/star/io/XActiveDataSink.hpp>
39 #include <com/sun/star/io/XOutputStream.hpp>
40 #include <com/sun/star/io/XSeekable.hpp>
41 #include <com/sun/star/sdbc/XRow.hpp>
42 #include <com/sun/star/task/XInteractionHandler.hpp>
43 #include <com/sun/star/ucb/CommandEnvironment.hpp>
44 #include <com/sun/star/ucb/CommandFailedException.hpp>
45 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
46 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
47 #include <com/sun/star/ucb/InsertCommandArgument2.hpp>
48 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
49 #include <com/sun/star/ucb/NameClash.hpp>
50 #include <com/sun/star/ucb/NameClashException.hpp>
51 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
52 #include <com/sun/star/ucb/OpenMode.hpp>
53 #include <com/sun/star/ucb/TransferInfo2.hpp>
54 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
55 #include <com/sun/star/ucb/XCommandInfo.hpp>
56 #include <com/sun/star/ucb/XContentAccess.hpp>
57 #include <com/sun/star/ucb/XContentCreator.hpp>
58 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
59 #include <com/sun/star/uno/Any.hxx>
60 #include <com/sun/star/uno/Sequence.hxx>
61 #include <ucbhelper/cancelcommandexecution.hxx>
62 #include <ucbhelper/simplenameclashresolverequest.hxx>
63 #include "ucbcmds.hxx"
66 using namespace com::sun::star
;
71 //=========================================================================
73 // struct TransferCommandContext.
75 //=========================================================================
77 struct TransferCommandContext
79 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
80 uno::Reference
< ucb::XCommandProcessor
> xProcessor
;
81 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
82 uno::Reference
< ucb::XCommandEnvironment
> xOrigEnv
;
83 ucb::GlobalTransferCommandArgument2 aArg
;
85 TransferCommandContext(
86 const uno::Reference
< lang::XMultiServiceFactory
> & rxSMgr
,
87 const uno::Reference
< ucb::XCommandProcessor
> & rxProcessor
,
88 const uno::Reference
< ucb::XCommandEnvironment
> & rxEnv
,
89 const uno::Reference
< ucb::XCommandEnvironment
> & rxOrigEnv
,
90 const ucb::GlobalTransferCommandArgument2
& rArg
)
91 : xSMgr( rxSMgr
), xProcessor( rxProcessor
), xEnv( rxEnv
),
92 xOrigEnv( rxOrigEnv
), aArg( rArg
) {}
95 //=========================================================================
97 // class InteractionHandlerProxy.
99 //=========================================================================
101 class InteractionHandlerProxy
:
102 public cppu::WeakImplHelper1
< task::XInteractionHandler
>
104 uno::Reference
< task::XInteractionHandler
> m_xOrig
;
107 InteractionHandlerProxy(
108 const uno::Reference
< task::XInteractionHandler
> & xOrig
)
109 : m_xOrig( xOrig
) {}
111 // XInteractionHandler methods.
112 virtual void SAL_CALL
handle(
113 const uno::Reference
< task::XInteractionRequest
>& Request
)
114 throw ( uno::RuntimeException
);
117 //=========================================================================
119 void SAL_CALL
InteractionHandlerProxy::handle(
120 const uno::Reference
< task::XInteractionRequest
>& Request
)
121 throw ( uno::RuntimeException
)
126 // Filter unwanted requests by just not handling them.
127 uno::Any aRequest
= Request
->getRequest();
130 ucb::InteractiveBadTransferURLException aBadTransferURLEx
;
131 if ( aRequest
>>= aBadTransferURLEx
)
138 ucb::UnsupportedNameClashException aUnsupportedNameClashEx
;
139 if ( aRequest
>>= aUnsupportedNameClashEx
)
141 if ( aUnsupportedNameClashEx
.NameClash
142 != ucb::NameClash::ERROR
)
148 ucb::NameClashException aNameClashEx
;
149 if ( aRequest
>>= aNameClashEx
)
156 ucb::UnsupportedCommandException aUnsupportedCommandEx
;
157 if ( aRequest
>>= aUnsupportedCommandEx
)
165 // not filtered; let the original handler do the work.
166 m_xOrig
->handle( Request
);
169 //=========================================================================
171 // class ActiveDataSink.
173 //=========================================================================
175 class ActiveDataSink
: public cppu::WeakImplHelper1
< io::XActiveDataSink
>
177 uno::Reference
< io::XInputStream
> m_xStream
;
180 // XActiveDataSink methods.
181 virtual void SAL_CALL
setInputStream(
182 const uno::Reference
< io::XInputStream
>& aStream
)
183 throw( uno::RuntimeException
);
184 virtual uno::Reference
< io::XInputStream
> SAL_CALL
getInputStream()
185 throw( uno::RuntimeException
);
188 //=========================================================================
190 void SAL_CALL
ActiveDataSink::setInputStream(
191 const uno::Reference
< io::XInputStream
>& aStream
)
192 throw( uno::RuntimeException
)
197 //=========================================================================
199 uno::Reference
< io::XInputStream
> SAL_CALL
ActiveDataSink::getInputStream()
200 throw( uno::RuntimeException
)
205 //=========================================================================
207 // class CommandProcessorInfo.
209 //=========================================================================
211 class CommandProcessorInfo
:
212 public cppu::WeakImplHelper1
< ucb::XCommandInfo
>
214 uno::Sequence
< ucb::CommandInfo
> * m_pInfo
;
217 CommandProcessorInfo();
218 virtual ~CommandProcessorInfo();
220 // XCommandInfo methods
221 virtual uno::Sequence
< ucb::CommandInfo
> SAL_CALL
getCommands()
222 throw( uno::RuntimeException
);
223 virtual ucb::CommandInfo SAL_CALL
224 getCommandInfoByName( const OUString
& Name
)
225 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
);
226 virtual ucb::CommandInfo SAL_CALL
227 getCommandInfoByHandle( sal_Int32 Handle
)
228 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
);
229 virtual sal_Bool SAL_CALL
hasCommandByName( const OUString
& Name
)
230 throw( uno::RuntimeException
);
231 virtual sal_Bool SAL_CALL
hasCommandByHandle( sal_Int32 Handle
)
232 throw( uno::RuntimeException
);
235 //=========================================================================
236 CommandProcessorInfo::CommandProcessorInfo()
238 m_pInfo
= new uno::Sequence
< ucb::CommandInfo
>( 2 );
242 OUString( GETCOMMANDINFO_NAME
), // Name
243 GETCOMMANDINFO_HANDLE
, // Handle
244 getCppuVoidType() ); // ArgType
247 OUString( GLOBALTRANSFER_NAME
), // Name
248 GLOBALTRANSFER_HANDLE
, // Handle
251 ucb::GlobalTransferCommandArgument
* >( 0 ) ) ); // ArgType
254 OUString( CHECKIN_NAME
), // Name
255 CHECKIN_HANDLE
, // Handle
258 ucb::GlobalTransferCommandArgument
* >( 0 ) ) ); // ArgType
261 //=========================================================================
263 CommandProcessorInfo::~CommandProcessorInfo()
268 //=========================================================================
270 uno::Sequence
< ucb::CommandInfo
> SAL_CALL
271 CommandProcessorInfo::getCommands()
272 throw( uno::RuntimeException
)
274 return uno::Sequence
< ucb::CommandInfo
>( *m_pInfo
);
277 //=========================================================================
279 ucb::CommandInfo SAL_CALL
280 CommandProcessorInfo::getCommandInfoByName( const OUString
& Name
)
281 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
)
283 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
285 if ( (*m_pInfo
)[ n
].Name
== Name
)
286 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
289 throw ucb::UnsupportedCommandException();
292 //=========================================================================
294 ucb::CommandInfo SAL_CALL
295 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle
)
296 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
)
298 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
300 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
301 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
304 throw ucb::UnsupportedCommandException();
307 //=========================================================================
309 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByName(
310 const OUString
& Name
)
311 throw( uno::RuntimeException
)
313 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
315 if ( (*m_pInfo
)[ n
].Name
== Name
)
322 //=========================================================================
324 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle
)
325 throw( uno::RuntimeException
)
327 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
329 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
336 //=========================================================================
337 //=========================================================================
338 //=========================================================================
340 OUString
createDesiredName(
341 const OUString
& rSourceURL
, const OUString
& rNewTitle
)
343 OUString
aName( rNewTitle
);
344 if ( aName
.isEmpty() )
346 // calculate name using source URL
348 // @@@ It's not guaranteed that slashes contained in the URL are
349 // actually path separators. This depends on the fact whether the
350 // URL is hierarchical. Only then the slashes are path separators.
351 // Therefore this algorithm is not guaranteed to work! But, ATM
352 // I don't know a better solution. It would have been better to
353 // have a member for the clashing name in
354 // UnsupportedNameClashException...
356 sal_Int32 nLastSlash
= rSourceURL
.lastIndexOf( '/' );
357 bool bTrailingSlash
= false;
358 if ( nLastSlash
== rSourceURL
.getLength() - 1 )
360 nLastSlash
= rSourceURL
.lastIndexOf( '/', nLastSlash
);
361 bTrailingSlash
= true;
364 if ( nLastSlash
!= -1 )
366 if ( bTrailingSlash
)
367 aName
= rSourceURL
.copy(
369 rSourceURL
.getLength() - nLastSlash
- 2 );
371 aName
= rSourceURL
.copy( nLastSlash
+ 1 );
378 // query, fragment present?
379 sal_Int32 nPos
= aName
.indexOf( '?' );
381 nPos
= aName
.indexOf( '#' );
384 aName
= aName
.copy( 0, nPos
);
386 return OUString( aName
);
389 OUString
createDesiredName(
390 const ucb::GlobalTransferCommandArgument
& rArg
)
392 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
395 OUString
createDesiredName(
396 const ucb::TransferInfo
& rArg
)
398 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
401 //=========================================================================
402 enum NameClashContinuation
{ NOT_HANDLED
, ABORT
, OVERWRITE
, NEW_NAME
, UNKNOWN
};
404 NameClashContinuation
interactiveNameClashResolve(
405 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
406 const OUString
& rTargetURL
,
407 const OUString
& rClashingName
,
408 /* [out] */ uno::Any
& rException
,
409 /* [out] */ OUString
& rNewName
)
411 rtl::Reference
< ucbhelper::SimpleNameClashResolveRequest
> xRequest(
412 new ucbhelper::SimpleNameClashResolveRequest(
413 rTargetURL
, // target folder URL
414 rClashingName
, // clashing name
415 OUString(), // no proposal for new name
416 sal_True
/* bSupportsOverwriteData */ ) );
418 rException
= xRequest
->getRequest();
421 uno::Reference
< task::XInteractionHandler
> xIH
422 = xEnv
->getInteractionHandler();
426 xIH
->handle( xRequest
.get() );
428 rtl::Reference
< ucbhelper::InteractionContinuation
>
429 xSelection( xRequest
->getSelection() );
431 if ( xSelection
.is() )
433 // Handler handled the request.
434 uno::Reference
< task::XInteractionAbort
> xAbort(
435 xSelection
.get(), uno::UNO_QUERY
);
444 ucb::XInteractionReplaceExistingData
>
446 xSelection
.get(), uno::UNO_QUERY
);
449 // Try again: Replace existing data.
455 ucb::XInteractionSupplyName
>
457 xSelection
.get(), uno::UNO_QUERY
);
458 if ( xSupplyName
.is() )
460 // Try again: Use new name.
461 rNewName
= xRequest
->getNewName();
466 OSL_FAIL( "Unknown interaction continuation!" );
477 //=========================================================================
479 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessor
,
480 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
481 const OUString
& rNewTitle
)
482 throw( uno::RuntimeException
)
486 uno::Sequence
< beans::PropertyValue
> aPropValues( 1 );
487 aPropValues
[ 0 ].Name
488 = OUString( "Title" );
489 aPropValues
[ 0 ].Handle
= -1;
490 aPropValues
[ 0 ].Value
= uno::makeAny( rNewTitle
);
492 ucb::Command
aSetPropsCommand(
493 OUString( "setPropertyValues" ),
495 uno::makeAny( aPropValues
) );
498 = xCommandProcessor
->execute( aSetPropsCommand
, 0, xEnv
);
500 uno::Sequence
< uno::Any
> aErrors
;
503 OSL_ENSURE( aErrors
.getLength() == 1,
504 "getPropertyValues return value invalid!" );
506 if ( aErrors
[ 0 ].hasValue() )
509 OSL_FAIL( "error setting Title property!" );
513 catch ( uno::RuntimeException
const & )
517 catch ( uno::Exception
const & )
525 //=========================================================================
526 uno::Reference
< ucb::XContent
> createNew(
527 const TransferCommandContext
& rContext
,
528 const uno::Reference
< ucb::XContent
> & xTarget
,
529 sal_Bool bSourceIsFolder
,
530 sal_Bool bSourceIsDocument
,
531 sal_Bool bSourceIsLink
)
532 throw( uno::Exception
)
534 //////////////////////////////////////////////////////////////////////
536 // (1) Obtain creatable types from target.
538 //////////////////////////////////////////////////////////////////////
540 // First, try it using "CreatabeleContentsInfo" property and
541 // "createNewContent" command -> the "new" way.
543 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorT(
544 xTarget
, uno::UNO_QUERY
);
545 if ( !xCommandProcessorT
.is() )
548 = uno::makeAny(beans::PropertyValue(
551 uno::makeAny(rContext
.aArg
.TargetURL
),
552 beans::PropertyState_DIRECT_VALUE
));
553 ucbhelper::cancelCommandExecution(
554 ucb::IOErrorCode_CANT_CREATE
,
555 uno::Sequence
< uno::Any
>(&aProps
, 1),
557 OUString("Target is no XCommandProcessor!"),
558 rContext
.xProcessor
);
562 uno::Sequence
< beans::Property
> aPropsToObtain( 1 );
563 aPropsToObtain
[ 0 ].Name
564 = OUString("CreatableContentsInfo");
565 aPropsToObtain
[ 0 ].Handle
568 ucb::Command
aGetPropsCommand(
569 OUString("getPropertyValues"),
571 uno::makeAny( aPropsToObtain
) );
573 uno::Reference
< sdbc::XRow
> xRow
;
574 xCommandProcessorT
->execute( aGetPropsCommand
, 0, rContext
.xEnv
) >>= xRow
;
576 uno::Sequence
< ucb::ContentInfo
> aTypesInfo
;
577 bool bGotTypesInfo
= false;
581 uno::Any aValue
= xRow
->getObject(
582 1, uno::Reference
< container::XNameAccess
>() );
583 if ( aValue
.hasValue() && ( aValue
>>= aTypesInfo
) )
585 bGotTypesInfo
= true;
589 uno::Reference
< ucb::XContentCreator
> xCreator
;
591 if ( !bGotTypesInfo
)
593 // Second, try it using XContentCreator interface -> the "old" way (not
594 // providing the chance to supply an XCommandEnvironment.
596 xCreator
.set( xTarget
, uno::UNO_QUERY
);
598 if ( !xCreator
.is() )
601 = uno::makeAny(beans::PropertyValue(
604 uno::makeAny(rContext
.aArg
.TargetURL
),
605 beans::PropertyState_DIRECT_VALUE
));
606 ucbhelper::cancelCommandExecution(
607 ucb::IOErrorCode_CANT_CREATE
,
608 uno::Sequence
< uno::Any
>(&aProps
, 1),
610 OUString("Target is no XContentCreator!"),
611 rContext
.xProcessor
);
615 aTypesInfo
= xCreator
->queryCreatableContentsInfo();
618 sal_Int32 nCount
= aTypesInfo
.getLength();
622 = uno::makeAny(beans::PropertyValue(
625 uno::makeAny(rContext
.aArg
.TargetURL
),
626 beans::PropertyState_DIRECT_VALUE
));
627 ucbhelper::cancelCommandExecution(
628 ucb::IOErrorCode_CANT_CREATE
,
629 uno::Sequence
< uno::Any
>(&aProps
, 1),
631 OUString("No types creatable!"),
632 rContext
.xProcessor
);
636 //////////////////////////////////////////////////////////////////////
638 // (2) Try to find a matching target type for the source object.
640 //////////////////////////////////////////////////////////////////////
642 uno::Reference
< ucb::XContent
> xNew
;
643 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
645 sal_Int32 nAttribs
= aTypesInfo
[ n
].Attributes
;
646 sal_Bool bMatch
= sal_False
;
648 if ( rContext
.aArg
.Operation
== ucb::TransferCommandOperation_LINK
)
652 if ( nAttribs
& ucb::ContentInfoAttribute::KIND_LINK
)
658 else if ( ( rContext
.aArg
.Operation
659 == ucb::TransferCommandOperation_COPY
) ||
660 ( rContext
.aArg
.Operation
661 == ucb::TransferCommandOperation_MOVE
) )
665 // Is source a link? Create link in target folder then.
668 if ( nAttribs
& ucb::ContentInfoAttribute::KIND_LINK
)
676 // (not a and not b) or (a and b)
677 // not( a or b) or (a and b)
679 if ( ( !!bSourceIsFolder
==
681 & ucb::ContentInfoAttribute::KIND_FOLDER
) )
683 ( !!bSourceIsDocument
==
685 & ucb::ContentInfoAttribute::KIND_DOCUMENT
) )
695 ucbhelper::cancelCommandExecution(
696 uno::makeAny( lang::IllegalArgumentException(
697 OUString( "Unknown transfer operation!" ),
706 //////////////////////////////////////////////////////////////
708 // (3) Create a new, empty object of matched type.
710 //////////////////////////////////////////////////////////////
712 if ( !xCreator
.is() )
714 // First, try it using "CreatabeleContentsInfo" property and
715 // "createNewContent" command -> the "new" way.
716 ucb::Command
aCreateNewCommand(
717 OUString("createNewContent"),
719 uno::makeAny( aTypesInfo
[ n
] ) );
721 xCommandProcessorT
->execute( aCreateNewCommand
, 0, rContext
.xEnv
)
726 // Second, try it using XContentCreator interface -> the "old"
727 // way (not providing the chance to supply an XCommandEnvironment.
729 xNew
= xCreator
->createNewContent( aTypesInfo
[ n
] );
736 beans::PropertyValue(
739 uno::makeAny(rContext
.aArg
.TargetURL
),
740 beans::PropertyState_DIRECT_VALUE
));
741 ucbhelper::cancelCommandExecution(
742 ucb::IOErrorCode_CANT_CREATE
,
743 uno::Sequence
< uno::Any
>(&aProps
, 1),
745 OUString( "createNewContent failed!" ),
746 rContext
.xProcessor
);
749 break; // escape from 'for' loop
756 //=========================================================================
757 void transferProperties(
758 const TransferCommandContext
& rContext
,
759 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
,
760 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorN
)
761 throw( uno::Exception
)
763 ucb::Command
aGetPropertySetInfoCommand(
764 OUString("getPropertySetInfo"),
768 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
769 xCommandProcessorS
->execute( aGetPropertySetInfoCommand
, 0, rContext
.xEnv
)
775 = uno::makeAny(beans::PropertyValue(
778 uno::makeAny(rContext
.aArg
.SourceURL
),
779 beans::PropertyState_DIRECT_VALUE
));
780 ucbhelper::cancelCommandExecution(
781 ucb::IOErrorCode_CANT_READ
,
782 uno::Sequence
< uno::Any
>(&aProps
, 1),
784 OUString( "Unable to get propertyset info from source object!" ),
785 rContext
.xProcessor
);
789 uno::Sequence
< beans::Property
> aAllProps
= xInfo
->getProperties();
791 ucb::Command
aGetPropsCommand1(
792 OUString("getPropertyValues"),
794 uno::makeAny( aAllProps
) );
796 uno::Reference
< sdbc::XRow
> xRow1
;
797 xCommandProcessorS
->execute(
798 aGetPropsCommand1
, 0, rContext
.xEnv
) >>= xRow1
;
803 = uno::makeAny(beans::PropertyValue(
806 uno::makeAny(rContext
.aArg
.SourceURL
),
807 beans::PropertyState_DIRECT_VALUE
));
808 ucbhelper::cancelCommandExecution(
809 ucb::IOErrorCode_CANT_READ
,
810 uno::Sequence
< uno::Any
>(&aProps
, 1),
812 OUString( "Unable to get properties from source object!" ),
813 rContext
.xProcessor
);
817 // Assemble data structure for setPropertyValues command.
819 // Note: Make room for additional Title and TargetURL too. -> + 2
820 uno::Sequence
< beans::PropertyValue
> aPropValues(
821 aAllProps
.getLength() + 2 );
823 sal_Bool bHasTitle
= rContext
.aArg
.NewTitle
.isEmpty();
824 sal_Bool bHasTargetURL
= ( rContext
.aArg
.Operation
825 != ucb::TransferCommandOperation_LINK
);
827 sal_Int32 nWritePos
= 0;
828 for ( sal_Int32 m
= 0; m
< aAllProps
.getLength(); ++m
)
830 const beans::Property
& rCurrProp
= aAllProps
[ m
];
831 beans::PropertyValue
& rCurrValue
= aPropValues
[ nWritePos
];
835 if ( rCurrProp
.Name
.compareToAscii( "Title" ) == 0 )
837 // Supply new title, if given.
840 bHasTitle
= sal_True
;
841 aValue
<<= rContext
.aArg
.NewTitle
;
844 else if ( rCurrProp
.Name
.compareToAscii( "TargetURL" ) == 0 )
846 // Supply source URL as link target for the new link to create.
847 if ( !bHasTargetURL
)
849 bHasTargetURL
= sal_True
;
850 aValue
<<= rContext
.aArg
.SourceURL
;
854 if ( !aValue
.hasValue() )
858 aValue
= xRow1
->getObject(
859 m
+ 1, uno::Reference
< container::XNameAccess
>() );
861 catch ( sdbc::SQLException
const & )
863 // Argh! But try to bring things to an end. Perhaps the
864 // mad property is not really important...
868 if ( aValue
.hasValue() )
870 rCurrValue
.Name
= rCurrProp
.Name
;
871 rCurrValue
.Handle
= rCurrProp
.Handle
;
872 rCurrValue
.Value
= aValue
;
873 // rCurrValue.State =
879 // Title needed, but not set yet?
880 if ( !bHasTitle
&& !rContext
.aArg
.NewTitle
.isEmpty() )
882 aPropValues
[ nWritePos
].Name
884 aPropValues
[ nWritePos
].Handle
= -1;
885 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.NewTitle
;
890 // TargetURL needed, but not set yet?
891 if ( !bHasTargetURL
&& ( rContext
.aArg
.Operation
892 == ucb::TransferCommandOperation_LINK
) )
894 aPropValues
[ nWritePos
].Name
895 = OUString("TargetURL");
896 aPropValues
[ nWritePos
].Handle
= -1;
897 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.SourceURL
;
902 aPropValues
.realloc( nWritePos
);
904 // Set properties at new object.
906 ucb::Command
aSetPropsCommand(
907 OUString("setPropertyValues"),
909 uno::makeAny( aPropValues
) );
911 xCommandProcessorN
->execute( aSetPropsCommand
, 0, rContext
.xEnv
);
913 // @@@ What to do with source props that are not supported by the
914 // new object? addProperty ???
917 //=========================================================================
918 uno::Reference
< io::XInputStream
> getInputStream(
919 const TransferCommandContext
& rContext
,
920 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
921 throw( uno::Exception
)
923 uno::Reference
< io::XInputStream
> xInputStream
;
925 //////////////////////////////////////////////////////////////////////
927 // (1) Try to get data as XInputStream via XActiveDataSink.
929 //////////////////////////////////////////////////////////////////////
933 uno::Reference
< io::XActiveDataSink
> xSink
= new ActiveDataSink
;
935 ucb::OpenCommandArgument2 aArg
;
936 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
937 aArg
.Priority
= 0; // unused
939 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 ); // unused
941 ucb::Command
aOpenCommand(
944 uno::makeAny( aArg
) );
946 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
947 xInputStream
= xSink
->getInputStream();
949 catch ( uno::RuntimeException
const & )
953 catch ( uno::Exception
const & )
955 // will be handled below.
958 if ( !xInputStream
.is() )
960 //////////////////////////////////////////////////////////////////
962 // (2) Try to get data via XOutputStream.
964 //////////////////////////////////////////////////////////////////
968 uno::Reference
< io::XOutputStream
> xOutputStream( io::Pipe::create(comphelper::getComponentContext(rContext
.xSMgr
)), uno::UNO_QUERY_THROW
);
970 ucb::OpenCommandArgument2 aArg
;
971 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
972 aArg
.Priority
= 0; // unused
973 aArg
.Sink
= xOutputStream
;
974 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 );
976 ucb::Command
aOpenCommand(
979 uno::makeAny( aArg
) );
981 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
983 xInputStream
= uno::Reference
< io::XInputStream
>(
984 xOutputStream
, uno::UNO_QUERY
);
986 catch ( uno::RuntimeException
const & )
990 catch ( uno::Exception
const & )
992 OSL_FAIL( "unable to get input stream from document!" );
999 //=========================================================================
1000 uno::Reference
< sdbc::XResultSet
> getResultSet(
1001 const TransferCommandContext
& rContext
,
1002 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
1003 throw( uno::Exception
)
1005 uno::Reference
< sdbc::XResultSet
> xResultSet
;
1007 uno::Sequence
< beans::Property
> aProps( 3 );
1009 aProps
[ 0 ].Name
= OUString("IsFolder");
1010 aProps
[ 0 ].Handle
= -1; /* unknown */
1011 aProps
[ 1 ].Name
= OUString("IsDocument");
1012 aProps
[ 1 ].Handle
= -1; /* unknown */
1013 aProps
[ 2 ].Name
= OUString("TargetURL");
1014 aProps
[ 2 ].Handle
= -1; /* unknown */
1016 ucb::OpenCommandArgument2 aArg
;
1017 aArg
.Mode
= ucb::OpenMode::ALL
;
1018 aArg
.Priority
= 0; // unused
1020 aArg
.Properties
= aProps
;
1022 ucb::Command
aOpenCommand( OUString("open"),
1024 uno::makeAny( aArg
) );
1027 uno::Reference
< ucb::XDynamicResultSet
> xSet
;
1028 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
) >>= xSet
;
1031 xResultSet
= xSet
->getStaticResultSet();
1033 catch ( uno::RuntimeException
const & )
1037 catch ( uno::Exception
const & )
1039 OSL_FAIL( "unable to get result set from folder!" );
1045 //=========================================================================
1046 void handleNameClashRename(
1047 const TransferCommandContext
& rContext
,
1048 const uno::Reference
< ucb::XContent
> & xNew
,
1049 const uno::Reference
<
1050 ucb::XCommandProcessor
> & xCommandProcessorN
,
1051 const uno::Reference
<
1052 ucb::XCommandProcessor
> & xCommandProcessorS
,
1053 /* [inout] */ uno::Reference
< io::XInputStream
> & xInputStream
)
1054 throw( uno::Exception
)
1058 // Obtain old title.
1059 uno::Sequence
< beans::Property
> aProps( 1 );
1060 aProps
[ 0 ].Name
= OUString("Title");
1061 aProps
[ 0 ].Handle
= -1;
1063 ucb::Command
aGetPropsCommand(
1064 OUString("getPropertyValues"),
1066 uno::makeAny( aProps
) );
1068 uno::Reference
< sdbc::XRow
> xRow
;
1069 xCommandProcessorN
->execute( aGetPropsCommand
, 0, rContext
.xEnv
) >>= xRow
;
1075 beans::PropertyValue(
1079 xNew
->getIdentifier()->getContentIdentifier() ),
1080 beans::PropertyState_DIRECT_VALUE
) );
1081 ucbhelper::cancelCommandExecution(
1082 ucb::IOErrorCode_CANT_READ
,
1083 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1085 OUString( "Unable to get properties from new object!" ),
1086 rContext
.xProcessor
);
1090 OUString aOldTitle
= xRow
->getString( 1 );
1091 if ( aOldTitle
.isEmpty() )
1093 ucbhelper::cancelCommandExecution(
1094 uno::makeAny( beans::UnknownPropertyException(
1095 OUString( "Unable to get property 'Title' from new object!" ),
1096 rContext
.xProcessor
) ),
1097 rContext
.xOrigEnv
);
1101 // Some pseudo-intelligence for not destroying file extensions.
1102 OUString aOldTitlePre
;
1103 OUString aOldTitlePost
;
1104 sal_Int32 nPos
= aOldTitle
.lastIndexOf( '.' );
1107 aOldTitlePre
= aOldTitle
.copy( 0, nPos
);
1108 aOldTitlePost
= aOldTitle
.copy( nPos
);
1111 aOldTitlePre
= aOldTitle
;
1114 aOldTitlePre
+= OUString("_");
1116 sal_Bool bContinue
= sal_True
;
1121 OUString aNewTitle
= aOldTitlePre
;
1122 aNewTitle
+= OUString::valueOf( nTry
);
1123 aNewTitle
+= aOldTitlePost
;
1126 setTitle( xCommandProcessorN
, rContext
.xEnv
, aNewTitle
);
1128 // Retry inserting the content.
1131 // Previous try may have read from stream. Seek to begin (if
1132 // optional interface XSeekable is supported) or get a new stream.
1133 if ( xInputStream
.is() )
1135 uno::Reference
< io::XSeekable
> xSeekable(
1136 xInputStream
, uno::UNO_QUERY
);
1137 if ( xSeekable
.is() )
1141 xSeekable
->seek( 0 );
1143 catch ( lang::IllegalArgumentException
const & )
1145 xInputStream
.clear();
1147 catch ( io::IOException
const & )
1149 xInputStream
.clear();
1153 xInputStream
.clear();
1155 if ( !xInputStream
.is() )
1158 = getInputStream( rContext
, xCommandProcessorS
);
1159 if ( !xInputStream
.is() )
1163 beans::PropertyValue(
1167 xNew
->getIdentifier()->
1168 getContentIdentifier() ),
1169 beans::PropertyState_DIRECT_VALUE
) );
1170 ucbhelper::cancelCommandExecution(
1171 ucb::IOErrorCode_CANT_READ
,
1172 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1174 OUString( "Got no data stream from source!" ),
1175 rContext
.xProcessor
);
1181 ucb::InsertCommandArgument2 aArg
;
1182 aArg
.Data
= xInputStream
;
1183 aArg
.ReplaceExisting
= sal_False
;
1185 ucb::Command
aInsertCommand(
1188 uno::makeAny( aArg
) );
1190 xCommandProcessorN
->execute( aInsertCommand
, 0, rContext
.xEnv
);
1193 bContinue
= sal_False
;
1195 catch ( uno::RuntimeException
const & )
1199 catch ( uno::Exception
const & )
1203 while ( bContinue
&& ( nTry
< 50 ) );
1207 ucbhelper::cancelCommandExecution(
1209 ucb::UnsupportedNameClashException(
1210 OUString( "Unable to resolve name clash!" ),
1211 rContext
.xProcessor
,
1212 ucb::NameClash::RENAME
) ),
1213 rContext
.xOrigEnv
);
1218 //=========================================================================
1219 void globalTransfer_(
1220 const TransferCommandContext
& rContext
,
1221 const uno::Reference
< ucb::XContent
> & xSource
,
1222 const uno::Reference
< ucb::XContent
> & xTarget
,
1223 const uno::Reference
< sdbc::XRow
> & xSourceProps
)
1224 throw( uno::Exception
)
1226 // IsFolder: property is required.
1227 sal_Bool bSourceIsFolder
= xSourceProps
->getBoolean( 1 );
1228 if ( !bSourceIsFolder
&& xSourceProps
->wasNull() )
1230 ucbhelper::cancelCommandExecution(
1231 uno::makeAny( beans::UnknownPropertyException(
1232 OUString( "Unable to get property 'IsFolder' "
1233 "from source object!" ),
1234 rContext
.xProcessor
) ),
1235 rContext
.xOrigEnv
);
1239 // IsDocument: property is required.
1240 sal_Bool bSourceIsDocument
= xSourceProps
->getBoolean( 2 );
1241 if ( !bSourceIsDocument
&& xSourceProps
->wasNull() )
1243 ucbhelper::cancelCommandExecution(
1244 uno::makeAny( beans::UnknownPropertyException(
1245 OUString( "Unable to get property 'IsDocument' "
1246 "from source object!" ),
1247 rContext
.xProcessor
) ),
1248 rContext
.xOrigEnv
);
1252 // TargetURL: property is optional.
1253 sal_Bool bSourceIsLink
= !xSourceProps
->getString( 3 ).isEmpty();
1255 //////////////////////////////////////////////////////////////////////
1257 // (1) Try to find a matching target type for the source object and
1258 // create a new, empty object of that type.
1260 //////////////////////////////////////////////////////////////////////
1262 uno::Reference
< ucb::XContent
> xNew
= createNew( rContext
,
1270 = uno::makeAny(beans::PropertyValue(
1271 OUString( "Folder"),
1273 uno::makeAny(rContext
.aArg
.TargetURL
),
1274 beans::PropertyState_DIRECT_VALUE
));
1275 ucbhelper::cancelCommandExecution(
1276 ucb::IOErrorCode_CANT_CREATE
,
1277 uno::Sequence
< uno::Any
>(&aProps
, 1),
1279 OUString( "No matching content type at target!" ),
1280 rContext
.xProcessor
);
1284 //////////////////////////////////////////////////////////////////////
1286 // (2) Transfer property values from source to new object.
1288 //////////////////////////////////////////////////////////////////////
1290 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorN(
1291 xNew
, uno::UNO_QUERY
);
1292 if ( !xCommandProcessorN
.is() )
1295 = uno::makeAny(beans::PropertyValue(
1299 xNew
->getIdentifier()->
1300 getContentIdentifier()),
1301 beans::PropertyState_DIRECT_VALUE
));
1302 ucbhelper::cancelCommandExecution(
1303 ucb::IOErrorCode_CANT_WRITE
,
1304 uno::Sequence
< uno::Any
>(&aProps
, 1),
1306 OUString( "New content is not a XCommandProcessor!" ),
1307 rContext
.xProcessor
);
1311 // Obtain all properties from source.
1313 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorS(
1314 xSource
, uno::UNO_QUERY
);
1315 if ( !xCommandProcessorS
.is() )
1318 = uno::makeAny(beans::PropertyValue(
1321 uno::makeAny(rContext
.aArg
.SourceURL
),
1322 beans::PropertyState_DIRECT_VALUE
));
1323 ucbhelper::cancelCommandExecution(
1324 ucb::IOErrorCode_CANT_READ
,
1325 uno::Sequence
< uno::Any
>(&aProps
, 1),
1327 OUString( "Source content is not a XCommandProcessor!" ),
1328 rContext
.xProcessor
);
1332 transferProperties( rContext
, xCommandProcessorS
, xCommandProcessorN
);
1334 //////////////////////////////////////////////////////////////////////
1336 // (3) Try to obtain a data stream from source.
1338 //////////////////////////////////////////////////////////////////////
1340 uno::Reference
< io::XInputStream
> xInputStream
;
1342 if ( bSourceIsDocument
&& ( rContext
.aArg
.Operation
1343 != ucb::TransferCommandOperation_LINK
) )
1344 xInputStream
= getInputStream( rContext
, xCommandProcessorS
);
1346 //////////////////////////////////////////////////////////////////////
1348 // (4) Try to obtain a resultset (children) from source.
1350 //////////////////////////////////////////////////////////////////////
1352 uno::Reference
< sdbc::XResultSet
> xResultSet
;
1354 if ( bSourceIsFolder
&& ( rContext
.aArg
.Operation
1355 != ucb::TransferCommandOperation_LINK
) )
1356 xResultSet
= getResultSet( rContext
, xCommandProcessorS
);
1358 //////////////////////////////////////////////////////////////////////
1360 // (5) Insert (store) new content.
1362 //////////////////////////////////////////////////////////////////////
1364 ucb::InsertCommandArgument2 aArg
;
1365 aArg
.Data
= xInputStream
;
1366 aArg
.MimeType
= rContext
.aArg
.MimeType
;
1368 switch ( rContext
.aArg
.NameClash
)
1370 case ucb::NameClash::OVERWRITE
:
1371 aArg
.ReplaceExisting
= sal_True
;
1374 case ucb::NameClash::ERROR
:
1375 case ucb::NameClash::RENAME
:
1376 case ucb::NameClash::KEEP
: // deprecated
1377 case ucb::NameClash::ASK
:
1378 aArg
.ReplaceExisting
= sal_False
;
1382 aArg
.ReplaceExisting
= sal_False
;
1383 OSL_FAIL( "Unknown nameclash directive!" );
1387 OUString aDesiredName
= createDesiredName( rContext
.aArg
);
1396 ucb::Command
aInsertCommand(
1399 uno::makeAny( aArg
) );
1401 xCommandProcessorN
->execute( aInsertCommand
, 0, rContext
.xEnv
);
1403 catch ( ucb::UnsupportedNameClashException
const & exc
)
1405 OSL_ENSURE( !aArg
.ReplaceExisting
,
1406 "BUG: UnsupportedNameClashException not allowed here!" );
1408 if (exc
.NameClash
!= ucb::NameClash::ERROR
) {
1409 OSL_FAIL( "BUG: NameClash::ERROR expected!" );
1412 // No chance to solve name clashes, because I'm not able to detect
1413 // whether there is one.
1414 throw ucb::UnsupportedNameClashException(
1416 "Unable to resolve name clashes, no chance to detect "
1417 "that there is one!" ),
1418 rContext
.xProcessor
,
1419 rContext
.aArg
.NameClash
);
1421 catch ( ucb::NameClashException
const & )
1423 // The 'insert' command throws a NameClashException if the parameter
1424 // ReplaceExisting of the command's argument was set to false and
1425 // there exists a resource with a clashing name in the target folder
1426 // of the operation.
1428 // 'insert' command has no direct support for name clashes other
1429 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1430 // ( ReplaceExisting == true ). So we have to implement the
1431 // other name clash handling directives on top of the content.
1433 // @@@ 'insert' command should be extended that it accepts a
1434 // name clash handling directive, exactly like 'transfer' command.
1436 switch ( rContext
.aArg
.NameClash
)
1438 case ucb::NameClash::OVERWRITE
:
1440 ucbhelper::cancelCommandExecution(
1442 ucb::UnsupportedNameClashException(
1444 "BUG: insert + replace == true MUST NOT "
1445 "throw NameClashException." ),
1446 rContext
.xProcessor
,
1447 rContext
.aArg
.NameClash
) ),
1448 rContext
.xOrigEnv
);
1452 case ucb::NameClash::ERROR
:
1455 case ucb::NameClash::RENAME
:
1457 // "invent" a new valid title.
1458 handleNameClashRename( rContext
,
1466 case ucb::NameClash::ASK
:
1470 NameClashContinuation eCont
1471 = interactiveNameClashResolve(
1472 rContext
.xOrigEnv
, // always use original environment!
1473 rContext
.aArg
.TargetURL
, // target folder URL
1482 cppu::throwException( aExc
);
1486 // Handled, but not clear, how...
1487 // fall-thru intended.
1490 throw ucb::CommandFailedException(
1492 "abort requested via interaction "
1494 uno::Reference
< uno::XInterface
>(),
1499 OSL_ENSURE( aArg
.ReplaceExisting
== sal_False
,
1500 "Hu? ReplaceExisting already true?"
1502 aArg
.ReplaceExisting
= sal_True
;
1508 // set new name -> set "Title" property...
1509 if ( setTitle( xCommandProcessorN
,
1513 // remember suggested title...
1514 aDesiredName
= aNewTitle
;
1516 // ... and try again.
1521 // error setting title. Abort.
1522 throw ucb::CommandFailedException(
1523 OUString( "error setting Title property!" ),
1524 uno::Reference
< uno::XInterface
>(),
1531 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1535 case ucb::NameClash::KEEP
: // deprecated
1538 ucbhelper::cancelCommandExecution(
1540 ucb::UnsupportedNameClashException(
1542 "default action, don't know how to "
1543 "handle name clash" ),
1544 rContext
.xProcessor
,
1545 rContext
.aArg
.NameClash
) ),
1546 rContext
.xOrigEnv
);
1554 //////////////////////////////////////////////////////////////////////
1556 // (6) Process children of source.
1558 //////////////////////////////////////////////////////////////////////
1560 if ( xResultSet
.is() )
1564 // Iterate over children...
1566 uno::Reference
< sdbc::XRow
> xChildRow(
1567 xResultSet
, uno::UNO_QUERY
);
1569 if ( !xChildRow
.is() )
1573 beans::PropertyValue(
1576 uno::makeAny(rContext
.aArg
.SourceURL
),
1577 beans::PropertyState_DIRECT_VALUE
));
1578 ucbhelper::cancelCommandExecution(
1579 ucb::IOErrorCode_CANT_READ
,
1580 uno::Sequence
< uno::Any
>(&aProps
, 1),
1582 OUString( "Unable to get properties from children of source!" ),
1583 rContext
.xProcessor
);
1587 uno::Reference
< ucb::XContentAccess
> xChildAccess(
1588 xResultSet
, uno::UNO_QUERY
);
1590 if ( !xChildAccess
.is() )
1594 beans::PropertyValue(
1597 uno::makeAny(rContext
.aArg
.SourceURL
),
1598 beans::PropertyState_DIRECT_VALUE
));
1599 ucbhelper::cancelCommandExecution(
1600 ucb::IOErrorCode_CANT_READ
,
1601 uno::Sequence
< uno::Any
>(&aProps
, 1),
1603 OUString( "Unable to get children of source!" ),
1604 rContext
.xProcessor
);
1608 if ( xResultSet
->first() )
1610 ucb::GlobalTransferCommandArgument2
aTransArg(
1611 rContext
.aArg
.Operation
,
1612 OUString(), // SourceURL; filled later
1613 xNew
->getIdentifier()
1614 ->getContentIdentifier(), // TargetURL
1615 OUString(), // NewTitle;
1616 rContext
.aArg
.NameClash
,
1617 rContext
.aArg
.MimeType
);
1619 TransferCommandContext
aSubCtx(
1621 rContext
.xProcessor
,
1627 uno::Reference
< ucb::XContent
> xChild
1628 = xChildAccess
->queryContent();
1633 aSubCtx
.aArg
.SourceURL
1634 = xChild
->getIdentifier()->getContentIdentifier();
1636 globalTransfer_( aSubCtx
,
1642 while ( xResultSet
->next() );
1645 catch ( sdbc::SQLException
const & )
1651 uno::Reference
< ucb::XCommandProcessor
> xcp(
1652 xTarget
, uno::UNO_QUERY
);
1655 uno::Reference
< ucb::XCommandInfo
> xci
;
1660 OUString("getCommandInfo"),
1666 const OUString
cmdName("flush");
1667 if((aAny
>>= xci
) && xci
->hasCommandByName(cmdName
))
1676 catch( uno::Exception
const & )
1683 //=========================================================================
1685 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1687 //=========================================================================
1689 uno::Reference
< ucb::XCommandInfo
>
1690 UniversalContentBroker::getCommandInfo()
1692 return uno::Reference
< ucb::XCommandInfo
>( new CommandProcessorInfo() );
1695 //=========================================================================
1696 void UniversalContentBroker::globalTransfer(
1697 const ucb::GlobalTransferCommandArgument2
& rArg
,
1698 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1699 throw( uno::Exception
)
1701 // Use own command environment with own interaction handler intercepting
1702 // some interaction requests that shall not be handled by the user-supplied
1703 // interaction handler.
1704 uno::Reference
< ucb::XCommandEnvironment
> xLocalEnv
;
1707 uno::Reference
< uno::XComponentContext
> xCtx(
1708 comphelper::getComponentContext( m_xSMgr
) );
1710 xLocalEnv
.set( ucb::CommandEnvironment::create(
1712 new InteractionHandlerProxy( xEnv
->getInteractionHandler() ),
1713 xEnv
->getProgressHandler() ) );
1716 //////////////////////////////////////////////////////////////////////
1718 // (1) Try to transfer the content using 'transfer' command.
1720 //////////////////////////////////////////////////////////////////////
1722 uno::Reference
< ucb::XContent
> xTarget
;
1723 uno::Reference
< ucb::XContentIdentifier
> xId
1724 = createContentIdentifier( rArg
.TargetURL
);
1729 xTarget
= queryContent( xId
);
1731 catch ( ucb::IllegalIdentifierException
const & )
1736 if ( !xTarget
.is() )
1739 = uno::makeAny(beans::PropertyValue(
1742 uno::makeAny(rArg
.TargetURL
),
1743 beans::PropertyState_DIRECT_VALUE
));
1744 ucbhelper::cancelCommandExecution(
1745 ucb::IOErrorCode_CANT_READ
,
1746 uno::Sequence
< uno::Any
>(&aProps
, 1),
1748 OUString( "Can't instanciate target object!" ),
1753 if ( ( rArg
.Operation
== ucb::TransferCommandOperation_COPY
) ||
1754 ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
) )
1756 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1757 xTarget
, uno::UNO_QUERY
);
1758 if ( !xCommandProcessor
.is() )
1762 beans::PropertyValue(
1765 uno::makeAny(rArg
.TargetURL
),
1766 beans::PropertyState_DIRECT_VALUE
));
1767 ucbhelper::cancelCommandExecution(
1768 ucb::IOErrorCode_CANT_READ
,
1769 uno::Sequence
< uno::Any
>(&aProps
, 1),
1771 OUString( "Target content is not a XCommandProcessor!" ),
1776 ucb::TransferInfo2
aTransferArg(
1778 == ucb::TransferCommandOperation_MOVE
), // MoveData
1791 ucb::Command
aCommand(
1792 OUString( "transfer" ), // Name
1794 uno::makeAny( aTransferArg
) ); // Argument
1796 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
1798 // Command succeeded. We're done.
1801 catch ( ucb::InteractiveBadTransferURLException
const & )
1803 // Source URL is not supported by target. Try to transfer
1804 // the content "manually".
1806 catch ( ucb::UnsupportedCommandException
const & )
1808 // 'transfer' command is not supported by commandprocessor.
1809 // Try to transfer manually.
1811 catch ( ucb::UnsupportedNameClashException
const & exc
)
1813 OSL_ENSURE( aTransferArg
.NameClash
== exc
.NameClash
,
1814 "nameclash mismatch!" );
1815 if ( exc
.NameClash
== ucb::NameClash::ASK
)
1817 // Try to detect a name clash by invoking "transfer" with
1818 // NameClash::ERROR.
1821 ucb::TransferInfo2
aTransferArg1(
1822 aTransferArg
.MoveData
,
1823 aTransferArg
.SourceURL
,
1824 aTransferArg
.NewTitle
,
1825 ucb::NameClash::ERROR
,
1826 aTransferArg
.MimeType
);
1828 ucb::Command
aCommand1(
1829 OUString("transfer"),
1831 uno::makeAny( aTransferArg1
) );
1833 xCommandProcessor
->execute( aCommand1
, 0, xLocalEnv
);
1835 // Command succeeded. We're done.
1838 catch ( ucb::UnsupportedNameClashException
const & )
1840 // No chance to solve name clashes, because I'm not
1841 // able to detect whether there is one.
1842 throw exc
; // Not just 'throw;'!
1844 catch ( ucb::NameClashException
const & )
1846 // There's a clash. Use interaction handler to solve it.
1850 NameClashContinuation eCont
1851 = interactiveNameClashResolve(
1852 xEnv
, // always use original environment!
1853 rArg
.TargetURL
, // target folder URL
1855 aTransferArg
), // clashing name
1863 cppu::throwException( aExc
);
1867 // Handled, but not clear, how...
1868 // fall-thru intended.
1871 throw ucb::CommandFailedException(
1873 "abort requested via interaction "
1875 uno::Reference
< uno::XInterface
>(),
1880 aTransferArg
.NameClash
1881 = ucb::NameClash::OVERWRITE
;
1886 aTransferArg
.NewTitle
= aNewTitle
;
1891 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1903 //////////////////////////////////////////////////////////////////////
1905 // (2) Try to transfer the content "manually".
1907 //////////////////////////////////////////////////////////////////////
1909 uno::Reference
< ucb::XContent
> xSource
;
1912 uno::Reference
< ucb::XContentIdentifier
> xId2
1913 = createContentIdentifier( rArg
.SourceURL
);
1915 xSource
= queryContent( xId2
);
1917 catch ( ucb::IllegalIdentifierException
const & )
1919 // Error handling via "if ( !xSource.is() )" below.
1922 if ( !xSource
.is() )
1925 = uno::makeAny(beans::PropertyValue(
1928 uno::makeAny(rArg
.SourceURL
),
1929 beans::PropertyState_DIRECT_VALUE
));
1930 ucbhelper::cancelCommandExecution(
1931 ucb::IOErrorCode_CANT_READ
,
1932 uno::Sequence
< uno::Any
>(&aProps
, 1),
1934 OUString( "Can't instanciate source object!" ),
1939 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1940 xSource
, uno::UNO_QUERY
);
1941 if ( !xCommandProcessor
.is() )
1944 = uno::makeAny(beans::PropertyValue(
1947 uno::makeAny(rArg
.SourceURL
),
1948 beans::PropertyState_DIRECT_VALUE
));
1949 ucbhelper::cancelCommandExecution(
1950 ucb::IOErrorCode_CANT_READ
,
1951 uno::Sequence
< uno::Any
>(&aProps
, 1),
1953 OUString( "Source content is not a XCommandProcessor!" ),
1958 // Obtain interesting property values from source...
1960 uno::Sequence
< beans::Property
> aProps( 4 );
1962 aProps
[ 0 ].Name
= OUString("IsFolder");
1963 aProps
[ 0 ].Handle
= -1; /* unknown */
1964 aProps
[ 1 ].Name
= OUString("IsDocument");
1965 aProps
[ 1 ].Handle
= -1; /* unknown */
1966 aProps
[ 2 ].Name
= OUString("TargetURL");
1967 aProps
[ 2 ].Handle
= -1; /* unknown */
1968 aProps
[ 3 ].Name
= OUString("BaseURI");
1969 aProps
[ 3 ].Handle
= -1; /* unknown */
1971 ucb::Command
aGetPropsCommand(
1972 OUString("getPropertyValues"),
1974 uno::makeAny( aProps
) );
1976 uno::Reference
< sdbc::XRow
> xRow
;
1977 xCommandProcessor
->execute( aGetPropsCommand
, 0, xLocalEnv
) >>= xRow
;
1982 = uno::makeAny(beans::PropertyValue(
1985 uno::makeAny(rArg
.SourceURL
),
1986 beans::PropertyState_DIRECT_VALUE
));
1987 ucbhelper::cancelCommandExecution(
1988 ucb::IOErrorCode_CANT_READ
,
1989 uno::Sequence
< uno::Any
>(&aProps2
, 1),
1991 OUString( "Unable to get properties from source object!" ),
1996 TransferCommandContext
aTransferCtx(
1997 m_xSMgr
, this, xLocalEnv
, xEnv
, rArg
);
1999 if ( rArg
.NewTitle
.isEmpty() )
2001 // BaseURI: property is optional.
2002 OUString
aBaseURI( xRow
->getString( 4 ) );
2003 if ( !aBaseURI
.isEmpty() )
2005 aTransferCtx
.aArg
.NewTitle
2006 = createDesiredName( aBaseURI
, OUString() );
2011 globalTransfer_( aTransferCtx
, xSource
, xTarget
, xRow
);
2013 //////////////////////////////////////////////////////////////////////
2015 // (3) Delete source, if operation is MOVE.
2017 //////////////////////////////////////////////////////////////////////
2019 if ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
)
2023 ucb::Command
aCommand(
2024 OUString("delete"), // Name
2026 uno::makeAny( sal_Bool( sal_True
) ) ); // Argument
2028 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
2030 catch ( uno::Exception
const & )
2032 OSL_FAIL( "Cannot delete source object!" );
2038 uno::Any
UniversalContentBroker::checkIn( const ucb::CheckinArgument
& rArg
,
2039 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
) throw ( uno::Exception
)
2042 // Use own command environment with own interaction handler intercepting
2043 // some interaction requests that shall not be handled by the user-supplied
2044 // interaction handler.
2045 uno::Reference
< ucb::XCommandEnvironment
> xLocalEnv
;
2048 uno::Reference
< uno::XComponentContext
> xCtx(
2049 comphelper::getComponentContext( m_xSMgr
) );
2051 xLocalEnv
.set( ucb::CommandEnvironment::create(
2053 new InteractionHandlerProxy( xEnv
->getInteractionHandler() ),
2054 xEnv
->getProgressHandler() ) );
2057 uno::Reference
< ucb::XContent
> xTarget
;
2058 uno::Reference
< ucb::XContentIdentifier
> xId
2059 = createContentIdentifier( rArg
.TargetURL
);
2064 xTarget
= queryContent( xId
);
2066 catch ( ucb::IllegalIdentifierException
const & )
2071 if ( !xTarget
.is() )
2074 = uno::makeAny(beans::PropertyValue(
2075 OUString( "Uri" ), -1,
2076 uno::makeAny( rArg
.TargetURL
),
2077 beans::PropertyState_DIRECT_VALUE
) );
2078 ucbhelper::cancelCommandExecution(
2079 ucb::IOErrorCode_CANT_READ
,
2080 uno::Sequence
< uno::Any
>( &aProps
, 1 ),
2082 OUString( "Can't instanciate target object!" ),
2087 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
2088 xTarget
, uno::UNO_QUERY
);
2089 if ( !xCommandProcessor
.is() )
2093 beans::PropertyValue(
2094 OUString( "Uri" ), -1,
2095 uno::makeAny( rArg
.TargetURL
),
2096 beans::PropertyState_DIRECT_VALUE
) );
2097 ucbhelper::cancelCommandExecution(
2098 ucb::IOErrorCode_CANT_READ
,
2099 uno::Sequence
< uno::Any
>( &aProps
, 1 ),
2101 OUString( "Target content is not a XCommandProcessor!" ),
2108 ucb::Command
aCommand(
2109 OUString( "checkin" ), -1,
2110 uno::makeAny( rArg
) );
2112 aRet
= xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
2114 catch ( ucb::UnsupportedCommandException
const & )
2116 // 'checkin' command is not supported by commandprocessor:
2122 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */