1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ucbcmds.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 /**************************************************************************
36 **************************************************************************
38 *************************************************************************/
39 #include <osl/diagnose.h>
40 #include <cppuhelper/implbase1.hxx>
41 #include <cppuhelper/exc_hlp.hxx>
42 #include <rtl/ustring.h>
43 #include <rtl/ustring.hxx>
44 #ifndef __COM_SUN_STAR_LANG_XINTERFACE_HPP_
45 #include <com/sun/star/uno/XInterface.hpp>
47 #include <com/sun/star/beans/PropertyState.hpp>
48 #include <com/sun/star/beans/PropertyValue.hpp>
49 #include <com/sun/star/container/XChild.hpp>
50 #include <com/sun/star/beans/XPropertySetInfo.hpp>
51 #include <com/sun/star/io/XActiveDataSink.hpp>
52 #include <com/sun/star/io/XOutputStream.hpp>
53 #include <com/sun/star/io/XSeekable.hpp>
54 #include <com/sun/star/sdbc/XRow.hpp>
55 #include <com/sun/star/task/XInteractionHandler.hpp>
56 #include <com/sun/star/ucb/CommandFailedException.hpp>
57 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
58 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp>
59 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
60 #ifndef _COM_SUN_STAR_UCB_INTERACTIVEBADTRANSFRERURLEXCEPTION_HPP_
61 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
63 #include <com/sun/star/ucb/NameClash.hpp>
64 #include <com/sun/star/ucb/NameClashException.hpp>
65 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
66 #include <com/sun/star/ucb/OpenMode.hpp>
67 #include <com/sun/star/ucb/TransferInfo.hpp>
68 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
69 #include <com/sun/star/ucb/XCommandInfo.hpp>
70 #include <com/sun/star/ucb/XContentAccess.hpp>
71 #include <com/sun/star/ucb/XContentCreator.hpp>
72 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
73 #include <com/sun/star/uno/Any.hxx>
74 #include <com/sun/star/uno/Sequence.hxx>
75 #include <ucbhelper/cancelcommandexecution.hxx>
76 #include <ucbhelper/simplenameclashresolverequest.hxx>
77 #include "ucbcmds.hxx"
80 using namespace com::sun::star
;
82 namespace ucb_commands
85 //=========================================================================
87 // struct TransferCommandContext.
89 //=========================================================================
91 struct TransferCommandContext
93 uno::Reference
< lang::XMultiServiceFactory
> xSMgr
;
94 uno::Reference
< ucb::XCommandProcessor
> xProcessor
;
95 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
96 uno::Reference
< ucb::XCommandEnvironment
> xOrigEnv
;
97 ucb::GlobalTransferCommandArgument aArg
;
99 TransferCommandContext(
100 const uno::Reference
< lang::XMultiServiceFactory
> & rxSMgr
,
101 const uno::Reference
< ucb::XCommandProcessor
> & rxProcessor
,
102 const uno::Reference
< ucb::XCommandEnvironment
> & rxEnv
,
103 const uno::Reference
< ucb::XCommandEnvironment
> & rxOrigEnv
,
104 const ucb::GlobalTransferCommandArgument
& rArg
)
105 : xSMgr( rxSMgr
), xProcessor( rxProcessor
), xEnv( rxEnv
),
106 xOrigEnv( rxOrigEnv
), aArg( rArg
) {}
109 //=========================================================================
111 // class InteractionHandlerProxy.
113 //=========================================================================
115 class InteractionHandlerProxy
:
116 public cppu::WeakImplHelper1
< task::XInteractionHandler
>
118 uno::Reference
< task::XInteractionHandler
> m_xOrig
;
121 InteractionHandlerProxy(
122 const uno::Reference
< task::XInteractionHandler
> & xOrig
)
123 : m_xOrig( xOrig
) {}
125 // XInteractionHandler methods.
126 virtual void SAL_CALL
handle(
127 const uno::Reference
< task::XInteractionRequest
>& Request
)
128 throw ( uno::RuntimeException
);
131 //=========================================================================
133 void SAL_CALL
InteractionHandlerProxy::handle(
134 const uno::Reference
< task::XInteractionRequest
>& Request
)
135 throw ( uno::RuntimeException
)
140 // Filter unwanted requests by just not handling them.
141 uno::Any aRequest
= Request
->getRequest();
144 ucb::InteractiveBadTransferURLException aBadTransferURLEx
;
145 if ( aRequest
>>= aBadTransferURLEx
)
152 ucb::UnsupportedNameClashException aUnsupportedNameClashEx
;
153 if ( aRequest
>>= aUnsupportedNameClashEx
)
155 if ( aUnsupportedNameClashEx
.NameClash
156 != ucb::NameClash::ERROR
)
162 ucb::NameClashException aNameClashEx
;
163 if ( aRequest
>>= aNameClashEx
)
170 ucb::UnsupportedCommandException aUnsupportedCommandEx
;
171 if ( aRequest
>>= aUnsupportedCommandEx
)
179 // not filtered; let the original handler do the work.
180 m_xOrig
->handle( Request
);
183 //=========================================================================
185 // class CommandEnvironment.
187 //=========================================================================
189 class CommandEnvironment
:
190 public cppu::WeakImplHelper1
< ucb::XCommandEnvironment
>
192 uno::Reference
< task::XInteractionHandler
> m_xIH
;
193 uno::Reference
< ucb::XProgressHandler
> m_xPH
;
197 const uno::Reference
< task::XInteractionHandler
> & xIH
,
198 const uno::Reference
< ucb::XProgressHandler
> & xPH
)
199 : m_xIH( xIH
), m_xPH( xPH
) {}
201 // XCommandEnvironment methods.
202 virtual uno::Reference
< task::XInteractionHandler
> SAL_CALL
203 getInteractionHandler()
204 throw ( uno::RuntimeException
);
205 virtual uno::Reference
< ucb::XProgressHandler
> SAL_CALL
207 throw ( uno::RuntimeException
);
210 //=========================================================================
212 uno::Reference
< task::XInteractionHandler
> SAL_CALL
213 CommandEnvironment::getInteractionHandler()
214 throw ( uno::RuntimeException
)
219 //=========================================================================
221 uno::Reference
< ucb::XProgressHandler
> SAL_CALL
222 CommandEnvironment::getProgressHandler()
223 throw ( uno::RuntimeException
)
228 //=========================================================================
230 // class ActiveDataSink.
232 //=========================================================================
234 class ActiveDataSink
: public cppu::WeakImplHelper1
< io::XActiveDataSink
>
236 uno::Reference
< io::XInputStream
> m_xStream
;
239 // XActiveDataSink methods.
240 virtual void SAL_CALL
setInputStream(
241 const uno::Reference
< io::XInputStream
>& aStream
)
242 throw( uno::RuntimeException
);
243 virtual uno::Reference
< io::XInputStream
> SAL_CALL
getInputStream()
244 throw( uno::RuntimeException
);
247 //=========================================================================
249 void SAL_CALL
ActiveDataSink::setInputStream(
250 const uno::Reference
< io::XInputStream
>& aStream
)
251 throw( uno::RuntimeException
)
256 //=========================================================================
258 uno::Reference
< io::XInputStream
> SAL_CALL
ActiveDataSink::getInputStream()
259 throw( uno::RuntimeException
)
264 //=========================================================================
266 // class CommandProcessorInfo.
268 //=========================================================================
270 class CommandProcessorInfo
:
271 public cppu::WeakImplHelper1
< ucb::XCommandInfo
>
273 uno::Sequence
< ucb::CommandInfo
> * m_pInfo
;
276 CommandProcessorInfo();
277 virtual ~CommandProcessorInfo();
279 // XCommandInfo methods
280 virtual uno::Sequence
< ucb::CommandInfo
> SAL_CALL
getCommands()
281 throw( uno::RuntimeException
);
282 virtual ucb::CommandInfo SAL_CALL
283 getCommandInfoByName( const rtl::OUString
& Name
)
284 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
);
285 virtual ucb::CommandInfo SAL_CALL
286 getCommandInfoByHandle( sal_Int32 Handle
)
287 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
);
288 virtual sal_Bool SAL_CALL
hasCommandByName( const rtl::OUString
& Name
)
289 throw( uno::RuntimeException
);
290 virtual sal_Bool SAL_CALL
hasCommandByHandle( sal_Int32 Handle
)
291 throw( uno::RuntimeException
);
294 //=========================================================================
295 CommandProcessorInfo::CommandProcessorInfo()
297 m_pInfo
= new uno::Sequence
< ucb::CommandInfo
>( 2 );
301 rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME
), // Name
302 GETCOMMANDINFO_HANDLE
, // Handle
303 getCppuVoidType() ); // ArgType
306 rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME
), // Name
307 GLOBALTRANSFER_HANDLE
, // Handle
310 ucb::GlobalTransferCommandArgument
* >( 0 ) ) ); // ArgType
313 //=========================================================================
315 CommandProcessorInfo::~CommandProcessorInfo()
320 //=========================================================================
322 uno::Sequence
< ucb::CommandInfo
> SAL_CALL
323 CommandProcessorInfo::getCommands()
324 throw( uno::RuntimeException
)
326 return uno::Sequence
< ucb::CommandInfo
>( *m_pInfo
);
329 //=========================================================================
331 ucb::CommandInfo SAL_CALL
332 CommandProcessorInfo::getCommandInfoByName( const rtl::OUString
& Name
)
333 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
)
335 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
337 if ( (*m_pInfo
)[ n
].Name
== Name
)
338 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
341 throw ucb::UnsupportedCommandException();
344 //=========================================================================
346 ucb::CommandInfo SAL_CALL
347 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle
)
348 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
)
350 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
352 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
353 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
356 throw ucb::UnsupportedCommandException();
359 //=========================================================================
361 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByName(
362 const rtl::OUString
& Name
)
363 throw( uno::RuntimeException
)
365 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
367 if ( (*m_pInfo
)[ n
].Name
== Name
)
374 //=========================================================================
376 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle
)
377 throw( uno::RuntimeException
)
379 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
381 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
388 //=========================================================================
389 //=========================================================================
390 //=========================================================================
392 static rtl::OUString
createDesiredName(
393 const rtl::OUString
& rSourceURL
, const rtl::OUString
& rNewTitle
)
395 rtl::OUString
aName( rNewTitle
);
396 if ( aName
.getLength() == 0 )
398 // calculate name using source URL
400 // @@@ It's not guaranteed that slashes contained in the URL are
401 // actually path separators. This depends on the fact whether the
402 // URL is hierarchical. Only then the slashes are path separators.
403 // Therefore this algorithm is not guaranteed to work! But, ATM
404 // I don't know a better solution. It would have been better to
405 // have a member for the clashing name in
406 // UnsupportedNameClashException...
408 sal_Int32 nLastSlash
= rSourceURL
.lastIndexOf( '/' );
409 bool bTrailingSlash
= false;
410 if ( nLastSlash
== rSourceURL
.getLength() - 1 )
412 nLastSlash
= rSourceURL
.lastIndexOf( '/', nLastSlash
);
413 bTrailingSlash
= true;
416 if ( nLastSlash
!= -1 )
418 if ( bTrailingSlash
)
419 aName
= rSourceURL
.copy(
421 rSourceURL
.getLength() - nLastSlash
- 2 );
423 aName
= rSourceURL
.copy( nLastSlash
+ 1 );
430 // query, fragment present?
431 sal_Int32 nPos
= aName
.indexOf( '?' );
433 nPos
= aName
.indexOf( '#' );
436 aName
= aName
.copy( 0, nPos
);
438 return rtl::OUString( aName
);
441 static rtl::OUString
createDesiredName(
442 const ucb::GlobalTransferCommandArgument
& rArg
)
444 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
447 static rtl::OUString
createDesiredName(
448 const ucb::TransferInfo
& rArg
)
450 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
453 //=========================================================================
454 enum NameClashContinuation
{ NOT_HANDLED
, ABORT
, OVERWRITE
, NEW_NAME
, UNKNOWN
};
456 static NameClashContinuation
interactiveNameClashResolve(
457 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
458 const rtl::OUString
& rTargetURL
,
459 const rtl::OUString
& rClashingName
,
460 /* [out] */ uno::Any
& rException
,
461 /* [out] */ rtl::OUString
& rNewName
)
463 rtl::Reference
< ucbhelper::SimpleNameClashResolveRequest
> xRequest(
464 new ucbhelper::SimpleNameClashResolveRequest(
465 rTargetURL
, // target folder URL
466 rClashingName
, // clashing name
467 rtl::OUString(), // no proposal for new name
468 sal_True
/* bSupportsOverwriteData */ ) );
470 rException
= xRequest
->getRequest();
473 uno::Reference
< task::XInteractionHandler
> xIH
474 = xEnv
->getInteractionHandler();
478 xIH
->handle( xRequest
.get() );
480 rtl::Reference
< ucbhelper::InteractionContinuation
>
481 xSelection( xRequest
->getSelection() );
483 if ( xSelection
.is() )
485 // Handler handled the request.
486 uno::Reference
< task::XInteractionAbort
> xAbort(
487 xSelection
.get(), uno::UNO_QUERY
);
496 ucb::XInteractionReplaceExistingData
>
498 xSelection
.get(), uno::UNO_QUERY
);
501 // Try again: Replace existing data.
507 ucb::XInteractionSupplyName
>
509 xSelection
.get(), uno::UNO_QUERY
);
510 if ( xSupplyName
.is() )
512 // Try again: Use new name.
513 rNewName
= xRequest
->getNewName();
518 OSL_ENSURE( sal_False
,
519 "Unknown interaction continuation!" );
530 //=========================================================================
531 static bool setTitle(
532 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessor
,
533 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
534 const rtl::OUString
& rNewTitle
)
535 throw( uno::RuntimeException
)
539 uno::Sequence
< beans::PropertyValue
> aPropValues( 1 );
540 aPropValues
[ 0 ].Name
541 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
542 aPropValues
[ 0 ].Handle
= -1;
543 aPropValues
[ 0 ].Value
= uno::makeAny( rNewTitle
);
545 ucb::Command
aSetPropsCommand(
546 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
548 uno::makeAny( aPropValues
) );
551 = xCommandProcessor
->execute( aSetPropsCommand
, 0, xEnv
);
553 uno::Sequence
< uno::Any
> aErrors
;
556 OSL_ENSURE( aErrors
.getLength() == 1,
557 "getPropertyValues return value invalid!" );
559 if ( aErrors
[ 0 ].hasValue() )
562 OSL_ENSURE( sal_False
, "error setting Title property!" );
566 catch ( uno::RuntimeException
const & )
570 catch ( uno::Exception
const & )
578 //=========================================================================
579 static uno::Reference
< ucb::XContent
> createNew(
580 const TransferCommandContext
& rContext
,
581 const uno::Reference
< ucb::XContent
> & xTarget
,
582 sal_Bool bSourceIsFolder
,
583 sal_Bool bSourceIsDocument
,
584 sal_Bool bSourceIsLink
)
585 throw( uno::Exception
)
587 //////////////////////////////////////////////////////////////////////
589 // (1) Obtain creatable types from target.
591 //////////////////////////////////////////////////////////////////////
593 uno::Reference
< ucb::XContentCreator
> xCreator(
594 xTarget
, uno::UNO_QUERY
);
596 if ( !xCreator
.is() )
599 = uno::makeAny(beans::PropertyValue(
600 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
603 uno::makeAny(rContext
.aArg
.TargetURL
),
604 beans::PropertyState_DIRECT_VALUE
));
605 ucbhelper::cancelCommandExecution(
606 ucb::IOErrorCode_CANT_CREATE
,
607 uno::Sequence
< uno::Any
>(&aProps
, 1),
609 rtl::OUString::createFromAscii( "Target is no XContentCreator!" ),
610 rContext
.xProcessor
);
614 uno::Sequence
< ucb::ContentInfo
> aTypesInfo
615 = xCreator
->queryCreatableContentsInfo();
617 sal_Int32 nCount
= aTypesInfo
.getLength();
621 = uno::makeAny(beans::PropertyValue(
622 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
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 rtl::OUString::createFromAscii( "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 rtl::OUString::createFromAscii(
698 "Unknown transfer operation!" ),
707 //////////////////////////////////////////////////////////////
709 // (3) Create a new, empty object of matched type.
711 //////////////////////////////////////////////////////////////
713 xNew
= xCreator
->createNewContent( aTypesInfo
[ n
] );
719 beans::PropertyValue(
720 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
723 uno::makeAny(rContext
.aArg
.TargetURL
),
724 beans::PropertyState_DIRECT_VALUE
));
725 ucbhelper::cancelCommandExecution(
726 ucb::IOErrorCode_CANT_CREATE
,
727 uno::Sequence
< uno::Any
>(&aProps
, 1),
729 rtl::OUString::createFromAscii(
730 "createNewContent failed!" ),
731 rContext
.xProcessor
);
734 break; // escape from 'for' loop
741 //=========================================================================
742 static void transferProperties(
743 const TransferCommandContext
& rContext
,
744 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
,
745 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorN
)
746 throw( uno::Exception
)
748 ucb::Command
aGetPropertySetInfoCommand(
749 rtl::OUString::createFromAscii( "getPropertySetInfo" ),
753 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
754 xCommandProcessorS
->execute( aGetPropertySetInfoCommand
, 0, rContext
.xEnv
)
760 = uno::makeAny(beans::PropertyValue(
761 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
764 uno::makeAny(rContext
.aArg
.SourceURL
),
765 beans::PropertyState_DIRECT_VALUE
));
766 ucbhelper::cancelCommandExecution(
767 ucb::IOErrorCode_CANT_READ
,
768 uno::Sequence
< uno::Any
>(&aProps
, 1),
770 rtl::OUString::createFromAscii(
771 "Unable to get propertyset info from source object!" ),
772 rContext
.xProcessor
);
776 uno::Sequence
< beans::Property
> aAllProps
= xInfo
->getProperties();
778 ucb::Command
aGetPropsCommand1(
779 rtl::OUString::createFromAscii( "getPropertyValues" ),
781 uno::makeAny( aAllProps
) );
783 uno::Reference
< sdbc::XRow
> xRow1
;
784 xCommandProcessorS
->execute(
785 aGetPropsCommand1
, 0, rContext
.xEnv
) >>= xRow1
;
790 = uno::makeAny(beans::PropertyValue(
791 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
794 uno::makeAny(rContext
.aArg
.SourceURL
),
795 beans::PropertyState_DIRECT_VALUE
));
796 ucbhelper::cancelCommandExecution(
797 ucb::IOErrorCode_CANT_READ
,
798 uno::Sequence
< uno::Any
>(&aProps
, 1),
800 rtl::OUString::createFromAscii(
801 "Unable to get properties from source object!" ),
802 rContext
.xProcessor
);
806 // Assemble data structure for setPropertyValues command.
808 // Note: Make room for additional Title and TargetURL too. -> + 2
809 uno::Sequence
< beans::PropertyValue
> aPropValues(
810 aAllProps
.getLength() + 2 );
812 sal_Bool bHasTitle
= ( rContext
.aArg
.NewTitle
.getLength() == 0 );
813 sal_Bool bHasTargetURL
= ( rContext
.aArg
.Operation
814 != ucb::TransferCommandOperation_LINK
);
816 sal_Int32 nWritePos
= 0;
817 for ( sal_Int32 m
= 0; m
< aAllProps
.getLength(); ++m
)
819 const beans::Property
& rCurrProp
= aAllProps
[ m
];
820 beans::PropertyValue
& rCurrValue
= aPropValues
[ nWritePos
];
824 if ( rCurrProp
.Name
.compareToAscii( "Title" ) == 0 )
826 // Supply new title, if given.
829 bHasTitle
= sal_True
;
830 aValue
<<= rContext
.aArg
.NewTitle
;
833 else if ( rCurrProp
.Name
.compareToAscii( "TargetURL" ) == 0 )
835 // Supply source URL as link target for the new link to create.
836 if ( !bHasTargetURL
)
838 bHasTargetURL
= sal_True
;
839 aValue
<<= rContext
.aArg
.SourceURL
;
843 if ( !aValue
.hasValue() )
847 aValue
= xRow1
->getObject(
848 m
+ 1, uno::Reference
< container::XNameAccess
>() );
850 catch ( sdbc::SQLException
const & )
852 // Argh! But try to bring things to an end. Perhaps the
853 // mad property is not really important...
857 if ( aValue
.hasValue() )
859 rCurrValue
.Name
= rCurrProp
.Name
;
860 rCurrValue
.Handle
= rCurrProp
.Handle
;
861 rCurrValue
.Value
= aValue
;
862 // rCurrValue.State =
868 // Title needed, but not set yet?
869 if ( !bHasTitle
&& ( rContext
.aArg
.NewTitle
.getLength() > 0 ) )
871 aPropValues
[ nWritePos
].Name
872 = rtl::OUString::createFromAscii( "Title" );
873 aPropValues
[ nWritePos
].Handle
= -1;
874 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.NewTitle
;
879 // TargetURL needed, but not set yet?
880 if ( !bHasTargetURL
&& ( rContext
.aArg
.Operation
881 == ucb::TransferCommandOperation_LINK
) )
883 aPropValues
[ nWritePos
].Name
884 = rtl::OUString::createFromAscii( "TargetURL" );
885 aPropValues
[ nWritePos
].Handle
= -1;
886 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.SourceURL
;
891 aPropValues
.realloc( nWritePos
);
893 // Set properties at new object.
895 ucb::Command
aSetPropsCommand(
896 rtl::OUString::createFromAscii( "setPropertyValues" ),
898 uno::makeAny( aPropValues
) );
900 xCommandProcessorN
->execute( aSetPropsCommand
, 0, rContext
.xEnv
);
902 // @@@ What to do with source props that are not supported by the
903 // new object? addProperty ???
906 //=========================================================================
907 static uno::Reference
< io::XInputStream
> getInputStream(
908 const TransferCommandContext
& rContext
,
909 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
910 throw( uno::Exception
)
912 uno::Reference
< io::XInputStream
> xInputStream
;
914 //////////////////////////////////////////////////////////////////////
916 // (1) Try to get data as XInputStream via XActiveDataSink.
918 //////////////////////////////////////////////////////////////////////
922 uno::Reference
< io::XActiveDataSink
> xSink
= new ActiveDataSink
;
924 ucb::OpenCommandArgument2 aArg
;
925 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
926 aArg
.Priority
= 0; // unused
928 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 ); // unused
930 ucb::Command
aOpenCommand(
931 rtl::OUString::createFromAscii( "open" ),
933 uno::makeAny( aArg
) );
935 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
936 xInputStream
= xSink
->getInputStream();
938 catch ( uno::RuntimeException
const & )
942 catch ( uno::Exception
const & )
944 // will be handled below.
947 if ( !xInputStream
.is() )
949 //////////////////////////////////////////////////////////////////
951 // (2) Try to get data via XOutputStream.
953 //////////////////////////////////////////////////////////////////
957 uno::Reference
< io::XOutputStream
> xOutputStream(
958 rContext
.xSMgr
->createInstance(
959 rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ),
962 if ( xOutputStream
.is() )
964 ucb::OpenCommandArgument2 aArg
;
965 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
966 aArg
.Priority
= 0; // unused
967 aArg
.Sink
= xOutputStream
;
968 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 );
970 ucb::Command
aOpenCommand(
971 rtl::OUString::createFromAscii( "open" ),
973 uno::makeAny( aArg
) );
975 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
977 xInputStream
= uno::Reference
< io::XInputStream
>(
978 xOutputStream
, uno::UNO_QUERY
);
981 catch ( uno::RuntimeException
const & )
985 catch ( uno::Exception
const & )
987 OSL_ENSURE( sal_False
, "unable to get input stream from document!" );
994 //=========================================================================
995 static uno::Reference
< sdbc::XResultSet
> getResultSet(
996 const TransferCommandContext
& rContext
,
997 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
998 throw( uno::Exception
)
1000 uno::Reference
< sdbc::XResultSet
> xResultSet
;
1002 uno::Sequence
< beans::Property
> aProps( 3 );
1004 aProps
[ 0 ].Name
= rtl::OUString::createFromAscii( "IsFolder" );
1005 aProps
[ 0 ].Handle
= -1; /* unknown */
1006 aProps
[ 1 ].Name
= rtl::OUString::createFromAscii( "IsDocument" );
1007 aProps
[ 1 ].Handle
= -1; /* unknown */
1008 aProps
[ 2 ].Name
= rtl::OUString::createFromAscii( "TargetURL" );
1009 aProps
[ 2 ].Handle
= -1; /* unknown */
1011 ucb::OpenCommandArgument2 aArg
;
1012 aArg
.Mode
= ucb::OpenMode::ALL
;
1013 aArg
.Priority
= 0; // unused
1015 aArg
.Properties
= aProps
;
1017 ucb::Command
aOpenCommand( rtl::OUString::createFromAscii( "open" ),
1019 uno::makeAny( aArg
) );
1022 uno::Reference
< ucb::XDynamicResultSet
> xSet
;
1023 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
) >>= xSet
;
1026 xResultSet
= xSet
->getStaticResultSet();
1028 catch ( uno::RuntimeException
const & )
1032 catch ( uno::Exception
const & )
1034 OSL_ENSURE( sal_False
, "unable to get result set from folder!" );
1040 //=========================================================================
1041 static void handleNameClashRename(
1042 const TransferCommandContext
& rContext
,
1043 const uno::Reference
< ucb::XContent
> & xNew
,
1044 const uno::Reference
<
1045 ucb::XCommandProcessor
> & xCommandProcessorN
,
1046 const uno::Reference
<
1047 ucb::XCommandProcessor
> & xCommandProcessorS
,
1048 /* [inout] */ uno::Reference
< io::XInputStream
> & xInputStream
)
1049 throw( uno::Exception
)
1053 // Obtain old title.
1054 uno::Sequence
< beans::Property
> aProps( 1 );
1055 aProps
[ 0 ].Name
= rtl::OUString::createFromAscii( "Title" );
1056 aProps
[ 0 ].Handle
= -1;
1058 ucb::Command
aGetPropsCommand(
1059 rtl::OUString::createFromAscii( "getPropertyValues" ),
1061 uno::makeAny( aProps
) );
1063 uno::Reference
< sdbc::XRow
> xRow
;
1064 xCommandProcessorN
->execute( aGetPropsCommand
, 0, rContext
.xEnv
) >>= xRow
;
1070 beans::PropertyValue(
1071 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1074 xNew
->getIdentifier()->getContentIdentifier() ),
1075 beans::PropertyState_DIRECT_VALUE
) );
1076 ucbhelper::cancelCommandExecution(
1077 ucb::IOErrorCode_CANT_READ
,
1078 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1080 rtl::OUString::createFromAscii(
1081 "Unable to get properties from new object!" ),
1082 rContext
.xProcessor
);
1086 rtl::OUString aOldTitle
= xRow
->getString( 1 );
1087 if ( !aOldTitle
.getLength() )
1089 ucbhelper::cancelCommandExecution(
1090 uno::makeAny( beans::UnknownPropertyException(
1091 rtl::OUString::createFromAscii(
1092 "Unable to get property 'Title' "
1093 "from new object!" ),
1094 rContext
.xProcessor
) ),
1095 rContext
.xOrigEnv
);
1099 // Some pseudo-intelligence for not destroying file extensions.
1100 rtl::OUString aOldTitlePre
;
1101 rtl::OUString aOldTitlePost
;
1102 sal_Int32 nPos
= aOldTitle
.lastIndexOf( '.' );
1105 aOldTitlePre
= aOldTitle
.copy( 0, nPos
);
1106 aOldTitlePost
= aOldTitle
.copy( nPos
);
1109 aOldTitlePre
= aOldTitle
;
1112 aOldTitlePre
+= rtl::OUString::createFromAscii( "_" );
1114 sal_Bool bContinue
= sal_True
;
1119 rtl::OUString aNewTitle
= aOldTitlePre
;
1120 aNewTitle
+= rtl::OUString::valueOf( nTry
);
1121 aNewTitle
+= aOldTitlePost
;
1124 setTitle( xCommandProcessorN
, rContext
.xEnv
, aNewTitle
);
1126 // Retry inserting the content.
1129 // Previous try may have read from stream. Seek to begin (if
1130 // optional interface XSeekable is supported) or get a new stream.
1131 if ( xInputStream
.is() )
1133 uno::Reference
< io::XSeekable
> xSeekable(
1134 xInputStream
, uno::UNO_QUERY
);
1135 if ( xSeekable
.is() )
1139 xSeekable
->seek( 0 );
1141 catch ( lang::IllegalArgumentException
const & )
1143 xInputStream
.clear();
1145 catch ( io::IOException
const & )
1147 xInputStream
.clear();
1151 xInputStream
.clear();
1153 if ( !xInputStream
.is() )
1156 = getInputStream( rContext
, xCommandProcessorS
);
1157 if ( !xInputStream
.is() )
1161 beans::PropertyValue(
1163 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1166 xNew
->getIdentifier()->
1167 getContentIdentifier() ),
1168 beans::PropertyState_DIRECT_VALUE
) );
1169 ucbhelper::cancelCommandExecution(
1170 ucb::IOErrorCode_CANT_READ
,
1171 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1173 rtl::OUString::createFromAscii(
1174 "Got no data stream from source!" ),
1175 rContext
.xProcessor
);
1181 ucb::InsertCommandArgument aArg
;
1182 aArg
.Data
= xInputStream
;
1183 aArg
.ReplaceExisting
= sal_False
;
1185 ucb::Command
aInsertCommand(
1186 rtl::OUString::createFromAscii( "insert" ),
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 rtl::OUString::createFromAscii(
1211 "Unable to resolve name clash!" ),
1212 rContext
.xProcessor
,
1213 ucb::NameClash::RENAME
) ),
1214 rContext
.xOrigEnv
);
1219 //=========================================================================
1220 static void globalTransfer(
1221 const TransferCommandContext
& rContext
,
1222 const uno::Reference
< ucb::XContent
> & xSource
,
1223 const uno::Reference
< ucb::XContent
> & xTarget
,
1224 const uno::Reference
< sdbc::XRow
> & xSourceProps
)
1225 throw( uno::Exception
)
1227 // IsFolder: property is required.
1228 sal_Bool bSourceIsFolder
= xSourceProps
->getBoolean( 1 );
1229 if ( !bSourceIsFolder
&& xSourceProps
->wasNull() )
1231 ucbhelper::cancelCommandExecution(
1232 uno::makeAny( beans::UnknownPropertyException(
1233 rtl::OUString::createFromAscii(
1234 "Unable to get property 'IsFolder' "
1235 "from source object!" ),
1236 rContext
.xProcessor
) ),
1237 rContext
.xOrigEnv
);
1241 // IsDocument: property is required.
1242 sal_Bool bSourceIsDocument
= xSourceProps
->getBoolean( 2 );
1243 if ( !bSourceIsDocument
&& xSourceProps
->wasNull() )
1245 ucbhelper::cancelCommandExecution(
1246 uno::makeAny( beans::UnknownPropertyException(
1247 rtl::OUString::createFromAscii(
1248 "Unable to get property 'IsDocument' "
1249 "from source object!" ),
1250 rContext
.xProcessor
) ),
1251 rContext
.xOrigEnv
);
1255 // TargetURL: property is optional.
1256 sal_Bool bSourceIsLink
= ( xSourceProps
->getString( 3 ).getLength() > 0 );
1258 //////////////////////////////////////////////////////////////////////
1260 // (1) Try to find a matching target type for the source object and
1261 // create a new, empty object of that type.
1263 //////////////////////////////////////////////////////////////////////
1265 uno::Reference
< ucb::XContent
> xNew
= createNew( rContext
,
1273 = uno::makeAny(beans::PropertyValue(
1274 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1277 uno::makeAny(rContext
.aArg
.TargetURL
),
1278 beans::PropertyState_DIRECT_VALUE
));
1279 ucbhelper::cancelCommandExecution(
1280 ucb::IOErrorCode_CANT_CREATE
,
1281 uno::Sequence
< uno::Any
>(&aProps
, 1),
1283 rtl::OUString::createFromAscii(
1284 "No matching content type at target!" ),
1285 rContext
.xProcessor
);
1289 //////////////////////////////////////////////////////////////////////
1291 // (2) Transfer property values from source to new object.
1293 //////////////////////////////////////////////////////////////////////
1295 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorN(
1296 xNew
, uno::UNO_QUERY
);
1297 if ( !xCommandProcessorN
.is() )
1300 = uno::makeAny(beans::PropertyValue(
1301 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1305 xNew
->getIdentifier()->
1306 getContentIdentifier()),
1307 beans::PropertyState_DIRECT_VALUE
));
1308 ucbhelper::cancelCommandExecution(
1309 ucb::IOErrorCode_CANT_WRITE
,
1310 uno::Sequence
< uno::Any
>(&aProps
, 1),
1312 rtl::OUString::createFromAscii(
1313 "New content is not a XCommandProcessor!" ),
1314 rContext
.xProcessor
);
1318 // Obtain all properties from source.
1320 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorS(
1321 xSource
, uno::UNO_QUERY
);
1322 if ( !xCommandProcessorS
.is() )
1325 = uno::makeAny(beans::PropertyValue(
1326 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1329 uno::makeAny(rContext
.aArg
.SourceURL
),
1330 beans::PropertyState_DIRECT_VALUE
));
1331 ucbhelper::cancelCommandExecution(
1332 ucb::IOErrorCode_CANT_READ
,
1333 uno::Sequence
< uno::Any
>(&aProps
, 1),
1335 rtl::OUString::createFromAscii(
1336 "Source content is not a XCommandProcessor!" ),
1337 rContext
.xProcessor
);
1341 transferProperties( rContext
, xCommandProcessorS
, xCommandProcessorN
);
1343 //////////////////////////////////////////////////////////////////////
1345 // (3) Try to obtain a data stream from source.
1347 //////////////////////////////////////////////////////////////////////
1349 uno::Reference
< io::XInputStream
> xInputStream
;
1351 if ( bSourceIsDocument
&& ( rContext
.aArg
.Operation
1352 != ucb::TransferCommandOperation_LINK
) )
1353 xInputStream
= getInputStream( rContext
, xCommandProcessorS
);
1355 //////////////////////////////////////////////////////////////////////
1357 // (4) Try to obtain a resultset (children) from source.
1359 //////////////////////////////////////////////////////////////////////
1361 uno::Reference
< sdbc::XResultSet
> xResultSet
;
1363 if ( bSourceIsFolder
&& ( rContext
.aArg
.Operation
1364 != ucb::TransferCommandOperation_LINK
) )
1365 xResultSet
= getResultSet( rContext
, xCommandProcessorS
);
1367 //////////////////////////////////////////////////////////////////////
1369 // (5) Insert (store) new content.
1371 //////////////////////////////////////////////////////////////////////
1373 ucb::InsertCommandArgument aArg
;
1374 aArg
.Data
= xInputStream
;
1376 switch ( rContext
.aArg
.NameClash
)
1378 case ucb::NameClash::OVERWRITE
:
1379 aArg
.ReplaceExisting
= sal_True
;
1382 case ucb::NameClash::ERROR
:
1383 case ucb::NameClash::RENAME
:
1384 case ucb::NameClash::KEEP
: // deprecated
1385 case ucb::NameClash::ASK
:
1386 aArg
.ReplaceExisting
= sal_False
;
1390 aArg
.ReplaceExisting
= sal_False
;
1391 OSL_ENSURE( sal_False
, "Unknown nameclash directive!" );
1395 rtl::OUString aDesiredName
= createDesiredName( rContext
.aArg
);
1404 ucb::Command
aInsertCommand(
1405 rtl::OUString::createFromAscii( "insert" ),
1407 uno::makeAny( aArg
) );
1409 xCommandProcessorN
->execute( aInsertCommand
, 0, rContext
.xEnv
);
1411 catch ( ucb::UnsupportedNameClashException
const & exc
)
1413 OSL_ENSURE( !aArg
.ReplaceExisting
,
1414 "BUG: UnsupportedNameClashException not allowed here!" );
1416 if (exc
.NameClash
!= ucb::NameClash::ERROR
) {
1417 OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" );
1420 // No chance to solve name clashes, because I'm not able to detect
1421 // whether there is one.
1422 throw ucb::UnsupportedNameClashException(
1423 rtl::OUString::createFromAscii(
1424 "Unable to resolve name clashes, no chance to detect "
1425 "that there is one!" ),
1426 rContext
.xProcessor
,
1427 rContext
.aArg
.NameClash
);
1429 catch ( ucb::NameClashException
const & )
1431 // The 'insert' command throws a NameClashException if the parameter
1432 // ReplaceExisting of the command's argument was set to false and
1433 // there exists a resource with a clashing name in the target folder
1434 // of the operation.
1436 // 'insert' command has no direct support for name clashes other
1437 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1438 // ( ReplaceExisting == true ). So we have to implement the
1439 // other name clash handling directives on top of the content.
1441 // @@@ 'insert' command should be extended that it accepts a
1442 // name clash handling directive, exactly like 'transfer' command.
1444 switch ( rContext
.aArg
.NameClash
)
1446 case ucb::NameClash::OVERWRITE
:
1448 ucbhelper::cancelCommandExecution(
1450 ucb::UnsupportedNameClashException(
1451 rtl::OUString::createFromAscii(
1452 "BUG: insert + replace == true MUST NOT "
1453 "throw NameClashException." ),
1454 rContext
.xProcessor
,
1455 rContext
.aArg
.NameClash
) ),
1456 rContext
.xOrigEnv
);
1460 case ucb::NameClash::ERROR
:
1463 case ucb::NameClash::RENAME
:
1465 // "invent" a new valid title.
1466 handleNameClashRename( rContext
,
1474 case ucb::NameClash::ASK
:
1477 rtl::OUString aNewTitle
;
1478 NameClashContinuation eCont
1479 = interactiveNameClashResolve(
1480 rContext
.xOrigEnv
, // always use original environment!
1481 rContext
.aArg
.TargetURL
, // target folder URL
1490 cppu::throwException( aExc
);
1494 // Handled, but not clear, how...
1495 // fall-thru intended.
1498 throw ucb::CommandFailedException(
1500 RTL_CONSTASCII_USTRINGPARAM(
1501 "abort requested via interaction "
1503 uno::Reference
< uno::XInterface
>(),
1508 OSL_ENSURE( aArg
.ReplaceExisting
== sal_False
,
1509 "Hu? ReplaceExisting already true?"
1511 aArg
.ReplaceExisting
= sal_True
;
1517 // set new name -> set "Title" property...
1518 if ( setTitle( xCommandProcessorN
,
1522 // remember suggested title...
1523 aDesiredName
= aNewTitle
;
1525 // ... and try again.
1530 // error setting title. Abort.
1531 throw ucb::CommandFailedException(
1533 RTL_CONSTASCII_USTRINGPARAM(
1534 "error setting Title property!"
1536 uno::Reference
< uno::XInterface
>(),
1543 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1547 case ucb::NameClash::KEEP
: // deprecated
1550 ucbhelper::cancelCommandExecution(
1552 ucb::UnsupportedNameClashException(
1554 RTL_CONSTASCII_USTRINGPARAM(
1555 "default action, don't know how to "
1556 "handle name clash" ) ),
1557 rContext
.xProcessor
,
1558 rContext
.aArg
.NameClash
) ),
1559 rContext
.xOrigEnv
);
1567 //////////////////////////////////////////////////////////////////////
1569 // (6) Process children of source.
1571 //////////////////////////////////////////////////////////////////////
1573 if ( xResultSet
.is() )
1577 // Iterate over children...
1579 uno::Reference
< sdbc::XRow
> xChildRow(
1580 xResultSet
, uno::UNO_QUERY
);
1582 if ( !xChildRow
.is() )
1586 beans::PropertyValue(
1587 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1590 uno::makeAny(rContext
.aArg
.SourceURL
),
1591 beans::PropertyState_DIRECT_VALUE
));
1592 ucbhelper::cancelCommandExecution(
1593 ucb::IOErrorCode_CANT_READ
,
1594 uno::Sequence
< uno::Any
>(&aProps
, 1),
1596 rtl::OUString::createFromAscii(
1597 "Unable to get properties from children of source!" ),
1598 rContext
.xProcessor
);
1602 uno::Reference
< ucb::XContentAccess
> xChildAccess(
1603 xResultSet
, uno::UNO_QUERY
);
1605 if ( !xChildAccess
.is() )
1609 beans::PropertyValue(
1610 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1613 uno::makeAny(rContext
.aArg
.SourceURL
),
1614 beans::PropertyState_DIRECT_VALUE
));
1615 ucbhelper::cancelCommandExecution(
1616 ucb::IOErrorCode_CANT_READ
,
1617 uno::Sequence
< uno::Any
>(&aProps
, 1),
1619 rtl::OUString::createFromAscii(
1620 "Unable to get children of source!" ),
1621 rContext
.xProcessor
);
1625 if ( xResultSet
->first() )
1627 ucb::GlobalTransferCommandArgument
aTransArg(
1628 rContext
.aArg
.Operation
, // Operation
1629 rtl::OUString(), // SourceURL; filled later
1630 xNew
->getIdentifier()
1631 ->getContentIdentifier(), // TargetURL
1632 rtl::OUString(), // NewTitle;
1633 rContext
.aArg
.NameClash
); // NameClash
1635 ucb_commands::TransferCommandContext
aSubCtx(
1637 rContext
.xProcessor
,
1643 uno::Reference
< ucb::XContent
> xChild
1644 = xChildAccess
->queryContent();
1649 aSubCtx
.aArg
.SourceURL
1650 = xChild
->getIdentifier()->getContentIdentifier();
1652 ucb_commands::globalTransfer( aSubCtx
,
1658 while ( xResultSet
->next() );
1661 catch ( sdbc::SQLException
const & )
1667 uno::Reference
< ucb::XCommandProcessor
> xcp(
1668 xTarget
, uno::UNO_QUERY
);
1671 uno::Reference
< ucb::XCommandInfo
> xci
;
1676 rtl::OUString::createFromAscii("getCommandInfo"),
1682 const rtl::OUString cmdName
=
1683 rtl::OUString::createFromAscii("flush");
1684 if((aAny
>>= xci
) && xci
->hasCommandByName(cmdName
))
1693 catch( uno::Exception
const & )
1698 } /* namescpace ucb_commands */
1700 //=========================================================================
1702 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1704 //=========================================================================
1706 uno::Reference
< ucb::XCommandInfo
>
1707 UniversalContentBroker::getCommandInfo()
1709 return uno::Reference
< ucb::XCommandInfo
>(
1710 new ucb_commands::CommandProcessorInfo() );
1713 //=========================================================================
1714 void UniversalContentBroker::globalTransfer(
1715 const ucb::GlobalTransferCommandArgument
& rArg
,
1716 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1717 throw( uno::Exception
)
1719 // Use own command environment with own interaction handler intercepting
1720 // some interaction requests that shell not be handled by the user-supplied
1721 // interaction handler.
1722 uno::Reference
< ucb::XCommandEnvironment
> xLocalEnv
;
1724 xLocalEnv
.set( new ucb_commands::CommandEnvironment(
1725 new ucb_commands::InteractionHandlerProxy(
1726 xEnv
->getInteractionHandler() ),
1727 xEnv
->getProgressHandler() ) );
1729 //////////////////////////////////////////////////////////////////////
1731 // (1) Try to transfer the content using 'transfer' command.
1733 //////////////////////////////////////////////////////////////////////
1735 uno::Reference
< ucb::XContent
> xTarget
;
1736 uno::Reference
< ucb::XContentIdentifier
> xId
1737 = createContentIdentifier( rArg
.TargetURL
);
1742 xTarget
= queryContent( xId
);
1744 catch ( ucb::IllegalIdentifierException
const & )
1749 if ( !xTarget
.is() )
1752 = uno::makeAny(beans::PropertyValue(
1753 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1756 uno::makeAny(rArg
.TargetURL
),
1757 beans::PropertyState_DIRECT_VALUE
));
1758 ucbhelper::cancelCommandExecution(
1759 ucb::IOErrorCode_CANT_READ
,
1760 uno::Sequence
< uno::Any
>(&aProps
, 1),
1762 rtl::OUString::createFromAscii(
1763 "Can't instanciate target object!" ),
1768 if ( ( rArg
.Operation
== ucb::TransferCommandOperation_COPY
) ||
1769 ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
) )
1771 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1772 xTarget
, uno::UNO_QUERY
);
1773 if ( !xCommandProcessor
.is() )
1777 beans::PropertyValue(
1778 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1781 uno::makeAny(rArg
.TargetURL
),
1782 beans::PropertyState_DIRECT_VALUE
));
1783 ucbhelper::cancelCommandExecution(
1784 ucb::IOErrorCode_CANT_READ
,
1785 uno::Sequence
< uno::Any
>(&aProps
, 1),
1787 rtl::OUString::createFromAscii(
1788 "Target content is not a XCommandProcessor!" ),
1793 ucb::TransferInfo
aTransferArg(
1795 == ucb::TransferCommandOperation_MOVE
), // MoveData
1796 rArg
.SourceURL
, // SourceURL
1797 rArg
.NewTitle
, // NewTitle
1798 rArg
.NameClash
); // NameClash
1807 ucb::Command
aCommand(
1808 rtl::OUString::createFromAscii( "transfer" ), // Name
1810 uno::makeAny( aTransferArg
) ); // Argument
1812 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
1814 // Command succeeded. We're done.
1817 catch ( ucb::InteractiveBadTransferURLException
const & )
1819 // Source URL is not supported by target. Try to transfer
1820 // the content "manually".
1822 catch ( ucb::UnsupportedCommandException
const & )
1824 // 'transfer' command is not supported by commandprocessor.
1825 // Try to transfer manually.
1827 catch ( ucb::UnsupportedNameClashException
const & exc
)
1829 OSL_ENSURE( aTransferArg
.NameClash
== exc
.NameClash
,
1830 "nameclash mismatch!" );
1831 if ( exc
.NameClash
== ucb::NameClash::ASK
)
1833 // Try to detect a name clash by invoking "transfer" with
1834 // NameClash::ERROR.
1837 ucb::TransferInfo
aTransferArg1(
1838 aTransferArg
.MoveData
,
1839 aTransferArg
.SourceURL
,
1840 aTransferArg
.NewTitle
,
1841 ucb::NameClash::ERROR
);
1843 ucb::Command
aCommand1(
1844 rtl::OUString::createFromAscii( "transfer" ),
1846 uno::makeAny( aTransferArg1
) );
1848 xCommandProcessor
->execute( aCommand1
, 0, xLocalEnv
);
1850 // Command succeeded. We're done.
1853 catch ( ucb::UnsupportedNameClashException
const & )
1855 // No chance to solve name clashes, because I'm not
1856 // able to detect whether there is one.
1857 throw exc
; // Not just 'throw;'!
1859 catch ( ucb::NameClashException
const & )
1861 // There's a clash. Use interaction handler to solve it.
1864 rtl::OUString aNewTitle
;
1865 ucb_commands::NameClashContinuation eCont
1866 = ucb_commands::interactiveNameClashResolve(
1867 xEnv
, // always use original environment!
1868 rArg
.TargetURL
, // target folder URL
1869 ucb_commands::createDesiredName(
1870 aTransferArg
), // clashing name
1876 case ucb_commands::NOT_HANDLED
:
1878 cppu::throwException( aExc
);
1881 case ucb_commands::UNKNOWN
:
1882 // Handled, but not clear, how...
1883 // fall-thru intended.
1885 case ucb_commands::ABORT
:
1886 throw ucb::CommandFailedException(
1888 RTL_CONSTASCII_USTRINGPARAM(
1889 "abort requested via interaction "
1891 uno::Reference
< uno::XInterface
>(),
1895 case ucb_commands::OVERWRITE
:
1896 aTransferArg
.NameClash
1897 = ucb::NameClash::OVERWRITE
;
1901 case ucb_commands::NEW_NAME
:
1902 aTransferArg
.NewTitle
= aNewTitle
;
1907 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1919 //////////////////////////////////////////////////////////////////////
1921 // (2) Try to transfer the content "manually".
1923 //////////////////////////////////////////////////////////////////////
1925 uno::Reference
< ucb::XContent
> xSource
;
1928 uno::Reference
< ucb::XContentIdentifier
> xId2
1929 = createContentIdentifier( rArg
.SourceURL
);
1931 xSource
= queryContent( xId2
);
1933 catch ( ucb::IllegalIdentifierException
const & )
1935 // Error handling via "if ( !xSource.is() )" below.
1938 if ( !xSource
.is() )
1941 = uno::makeAny(beans::PropertyValue(
1942 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1945 uno::makeAny(rArg
.SourceURL
),
1946 beans::PropertyState_DIRECT_VALUE
));
1947 ucbhelper::cancelCommandExecution(
1948 ucb::IOErrorCode_CANT_READ
,
1949 uno::Sequence
< uno::Any
>(&aProps
, 1),
1951 rtl::OUString::createFromAscii(
1952 "Can't instanciate source object!" ),
1957 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1958 xSource
, uno::UNO_QUERY
);
1959 if ( !xCommandProcessor
.is() )
1962 = uno::makeAny(beans::PropertyValue(
1963 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1966 uno::makeAny(rArg
.SourceURL
),
1967 beans::PropertyState_DIRECT_VALUE
));
1968 ucbhelper::cancelCommandExecution(
1969 ucb::IOErrorCode_CANT_READ
,
1970 uno::Sequence
< uno::Any
>(&aProps
, 1),
1972 rtl::OUString::createFromAscii(
1973 "Source content is not a XCommandProcessor!" ),
1978 // Obtain interesting property values from source...
1980 uno::Sequence
< beans::Property
> aProps( 4 );
1982 aProps
[ 0 ].Name
= rtl::OUString::createFromAscii( "IsFolder" );
1983 aProps
[ 0 ].Handle
= -1; /* unknown */
1984 aProps
[ 1 ].Name
= rtl::OUString::createFromAscii( "IsDocument" );
1985 aProps
[ 1 ].Handle
= -1; /* unknown */
1986 aProps
[ 2 ].Name
= rtl::OUString::createFromAscii( "TargetURL" );
1987 aProps
[ 2 ].Handle
= -1; /* unknown */
1988 aProps
[ 3 ].Name
= rtl::OUString::createFromAscii( "BaseURI" );
1989 aProps
[ 3 ].Handle
= -1; /* unknown */
1991 ucb::Command
aGetPropsCommand(
1992 rtl::OUString::createFromAscii( "getPropertyValues" ),
1994 uno::makeAny( aProps
) );
1996 uno::Reference
< sdbc::XRow
> xRow
;
1997 xCommandProcessor
->execute( aGetPropsCommand
, 0, xLocalEnv
) >>= xRow
;
2002 = uno::makeAny(beans::PropertyValue(
2003 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2006 uno::makeAny(rArg
.SourceURL
),
2007 beans::PropertyState_DIRECT_VALUE
));
2008 ucbhelper::cancelCommandExecution(
2009 ucb::IOErrorCode_CANT_READ
,
2010 uno::Sequence
< uno::Any
>(&aProps2
, 1),
2012 rtl::OUString::createFromAscii(
2013 "Unable to get properties from source object!" ),
2018 ucb_commands::TransferCommandContext
aTransferCtx(
2019 m_xSMgr
, this, xLocalEnv
, xEnv
, rArg
);
2021 if ( rArg
.NewTitle
.getLength() == 0 )
2023 // BaseURI: property is optional.
2024 rtl::OUString
aBaseURI( xRow
->getString( 4 ) );
2025 if ( aBaseURI
.getLength() )
2027 aTransferCtx
.aArg
.NewTitle
2028 = ucb_commands::createDesiredName( aBaseURI
, rtl::OUString() );
2033 ucb_commands::globalTransfer( aTransferCtx
, xSource
, xTarget
, xRow
);
2035 //////////////////////////////////////////////////////////////////////
2037 // (3) Delete source, if operation is MOVE.
2039 //////////////////////////////////////////////////////////////////////
2041 if ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
)
2045 ucb::Command
aCommand(
2046 rtl::OUString::createFromAscii( "delete" ), // Name
2048 uno::makeAny( sal_Bool( sal_True
) ) ); // Argument
2050 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
2052 catch ( uno::Exception
const & )
2054 OSL_ENSURE( sal_False
, "Cannot delete source object!" );