1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
21 #include <comphelper/processfactory.hxx>
22 #include <cppuhelper/implbase1.hxx>
23 #include <cppuhelper/exc_hlp.hxx>
24 #include <rtl/ustring.h>
25 #include <rtl/ustring.hxx>
26 #include <com/sun/star/uno/XInterface.hpp>
27 #include <com/sun/star/beans/PropertyState.hpp>
28 #include <com/sun/star/beans/PropertyValue.hpp>
29 #include <com/sun/star/container/XChild.hpp>
30 #include <com/sun/star/beans/XPropertySetInfo.hpp>
31 #include <com/sun/star/io/Pipe.hpp>
32 #include <com/sun/star/io/XActiveDataSink.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 #include <com/sun/star/sdbc/XRow.hpp>
36 #include <com/sun/star/task/XInteractionHandler.hpp>
37 #include <com/sun/star/ucb/CommandEnvironment.hpp>
38 #include <com/sun/star/ucb/CommandFailedException.hpp>
39 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
40 #include <com/sun/star/ucb/GlobalTransferCommandArgument2.hpp>
41 #include <com/sun/star/ucb/InsertCommandArgument2.hpp>
42 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
43 #include <com/sun/star/ucb/NameClash.hpp>
44 #include <com/sun/star/ucb/NameClashException.hpp>
45 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
46 #include <com/sun/star/ucb/OpenMode.hpp>
47 #include <com/sun/star/ucb/TransferInfo2.hpp>
48 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
49 #include <com/sun/star/ucb/XCommandInfo.hpp>
50 #include <com/sun/star/ucb/XContentAccess.hpp>
51 #include <com/sun/star/ucb/XContentCreator.hpp>
52 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
53 #include <com/sun/star/ucb/XInteractionSupplyName.hpp>
54 #include <com/sun/star/uno/Any.hxx>
55 #include <com/sun/star/uno/Sequence.hxx>
56 #include <ucbhelper/cancelcommandexecution.hxx>
57 #include <ucbhelper/simplenameclashresolverequest.hxx>
58 #include "ucbcmds.hxx"
61 using namespace com::sun::star
;
68 // struct TransferCommandContext.
72 struct TransferCommandContext
74 uno::Reference
< uno::XComponentContext
> m_xContext
;
75 uno::Reference
< ucb::XCommandProcessor
> xProcessor
;
76 uno::Reference
< ucb::XCommandEnvironment
> xEnv
;
77 uno::Reference
< ucb::XCommandEnvironment
> xOrigEnv
;
78 ucb::GlobalTransferCommandArgument2 aArg
;
80 TransferCommandContext(
81 const uno::Reference
< uno::XComponentContext
> & xContext
,
82 const uno::Reference
< ucb::XCommandProcessor
> & rxProcessor
,
83 const uno::Reference
< ucb::XCommandEnvironment
> & rxEnv
,
84 const uno::Reference
< ucb::XCommandEnvironment
> & rxOrigEnv
,
85 const ucb::GlobalTransferCommandArgument2
& rArg
)
86 : m_xContext( xContext
), xProcessor( rxProcessor
), xEnv( rxEnv
),
87 xOrigEnv( rxOrigEnv
), aArg( rArg
) {}
92 // class InteractionHandlerProxy.
96 class InteractionHandlerProxy
:
97 public cppu::WeakImplHelper1
< task::XInteractionHandler
>
99 uno::Reference
< task::XInteractionHandler
> m_xOrig
;
102 InteractionHandlerProxy(
103 const uno::Reference
< task::XInteractionHandler
> & xOrig
)
104 : m_xOrig( xOrig
) {}
106 // XInteractionHandler methods.
107 virtual void SAL_CALL
handle(
108 const uno::Reference
< task::XInteractionRequest
>& Request
)
109 throw ( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
114 void SAL_CALL
InteractionHandlerProxy::handle(
115 const uno::Reference
< task::XInteractionRequest
>& Request
)
116 throw ( uno::RuntimeException
, std::exception
)
121 // Filter unwanted requests by just not handling them.
122 uno::Any aRequest
= Request
->getRequest();
125 ucb::InteractiveBadTransferURLException aBadTransferURLEx
;
126 if ( aRequest
>>= aBadTransferURLEx
)
133 ucb::UnsupportedNameClashException aUnsupportedNameClashEx
;
134 if ( aRequest
>>= aUnsupportedNameClashEx
)
136 if ( aUnsupportedNameClashEx
.NameClash
137 != ucb::NameClash::ERROR
)
143 ucb::NameClashException aNameClashEx
;
144 if ( aRequest
>>= aNameClashEx
)
151 ucb::UnsupportedCommandException aUnsupportedCommandEx
;
152 if ( aRequest
>>= aUnsupportedCommandEx
)
160 // not filtered; let the original handler do the work.
161 m_xOrig
->handle( Request
);
166 // class ActiveDataSink.
170 class ActiveDataSink
: public cppu::WeakImplHelper1
< io::XActiveDataSink
>
172 uno::Reference
< io::XInputStream
> m_xStream
;
175 // XActiveDataSink methods.
176 virtual void SAL_CALL
setInputStream(
177 const uno::Reference
< io::XInputStream
>& aStream
)
178 throw( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
179 virtual uno::Reference
< io::XInputStream
> SAL_CALL
getInputStream()
180 throw( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
185 void SAL_CALL
ActiveDataSink::setInputStream(
186 const uno::Reference
< io::XInputStream
>& aStream
)
187 throw( uno::RuntimeException
, std::exception
)
194 uno::Reference
< io::XInputStream
> SAL_CALL
ActiveDataSink::getInputStream()
195 throw( uno::RuntimeException
, std::exception
)
202 // class CommandProcessorInfo.
206 class CommandProcessorInfo
:
207 public cppu::WeakImplHelper1
< ucb::XCommandInfo
>
209 uno::Sequence
< ucb::CommandInfo
> * m_pInfo
;
212 CommandProcessorInfo();
213 virtual ~CommandProcessorInfo();
215 // XCommandInfo methods
216 virtual uno::Sequence
< ucb::CommandInfo
> SAL_CALL
getCommands()
217 throw( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
218 virtual ucb::CommandInfo SAL_CALL
219 getCommandInfoByName( const OUString
& Name
)
220 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
221 virtual ucb::CommandInfo SAL_CALL
222 getCommandInfoByHandle( sal_Int32 Handle
)
223 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
224 virtual sal_Bool SAL_CALL
hasCommandByName( const OUString
& Name
)
225 throw( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
226 virtual sal_Bool SAL_CALL
hasCommandByHandle( sal_Int32 Handle
)
227 throw( uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
231 CommandProcessorInfo::CommandProcessorInfo()
233 m_pInfo
= new uno::Sequence
< ucb::CommandInfo
>( 2 );
237 OUString( GETCOMMANDINFO_NAME
), // Name
238 GETCOMMANDINFO_HANDLE
, // Handle
239 cppu::UnoType
<void>::get() ); // ArgType
242 OUString( GLOBALTRANSFER_NAME
), // Name
243 GLOBALTRANSFER_HANDLE
, // Handle
244 cppu::UnoType
<ucb::GlobalTransferCommandArgument
>::get() ); // ArgType
247 OUString( CHECKIN_NAME
), // Name
248 CHECKIN_HANDLE
, // Handle
249 cppu::UnoType
<ucb::CheckinArgument
>::get() ); // ArgType
254 CommandProcessorInfo::~CommandProcessorInfo()
261 uno::Sequence
< ucb::CommandInfo
> SAL_CALL
262 CommandProcessorInfo::getCommands()
263 throw( uno::RuntimeException
, std::exception
)
265 return uno::Sequence
< ucb::CommandInfo
>( *m_pInfo
);
270 ucb::CommandInfo SAL_CALL
271 CommandProcessorInfo::getCommandInfoByName( const OUString
& Name
)
272 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
, std::exception
)
274 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
276 if ( (*m_pInfo
)[ n
].Name
== Name
)
277 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
280 throw ucb::UnsupportedCommandException();
285 ucb::CommandInfo SAL_CALL
286 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle
)
287 throw( ucb::UnsupportedCommandException
, uno::RuntimeException
, std::exception
)
289 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
291 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
292 return ucb::CommandInfo( (*m_pInfo
)[ n
] );
295 throw ucb::UnsupportedCommandException();
300 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByName(
301 const OUString
& Name
)
302 throw( uno::RuntimeException
, std::exception
)
304 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
306 if ( (*m_pInfo
)[ n
].Name
== Name
)
315 sal_Bool SAL_CALL
CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle
)
316 throw( uno::RuntimeException
, std::exception
)
318 for ( sal_Int32 n
= 0; n
< m_pInfo
->getLength(); ++n
)
320 if ( (*m_pInfo
)[ n
].Handle
== Handle
)
331 OUString
createDesiredName(
332 const OUString
& rSourceURL
, const OUString
& rNewTitle
)
334 OUString
aName( rNewTitle
);
335 if ( aName
.isEmpty() )
337 // calculate name using source URL
339 // @@@ It's not guaranteed that slashes contained in the URL are
340 // actually path separators. This depends on the fact whether the
341 // URL is hierarchical. Only then the slashes are path separators.
342 // Therefore this algorithm is not guaranteed to work! But, ATM
343 // I don't know a better solution. It would have been better to
344 // have a member for the clashing name in
345 // UnsupportedNameClashException...
347 sal_Int32 nLastSlash
= rSourceURL
.lastIndexOf( '/' );
348 bool bTrailingSlash
= false;
349 if ( nLastSlash
== rSourceURL
.getLength() - 1 )
351 nLastSlash
= rSourceURL
.lastIndexOf( '/', nLastSlash
);
352 bTrailingSlash
= true;
355 if ( nLastSlash
!= -1 )
357 if ( bTrailingSlash
)
358 aName
= rSourceURL
.copy(
360 rSourceURL
.getLength() - nLastSlash
- 2 );
362 aName
= rSourceURL
.copy( nLastSlash
+ 1 );
369 // query, fragment present?
370 sal_Int32 nPos
= aName
.indexOf( '?' );
372 nPos
= aName
.indexOf( '#' );
375 aName
= aName
.copy( 0, nPos
);
377 return OUString( aName
);
380 OUString
createDesiredName(
381 const ucb::GlobalTransferCommandArgument
& rArg
)
383 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
386 OUString
createDesiredName(
387 const ucb::TransferInfo
& rArg
)
389 return createDesiredName( rArg
.SourceURL
, rArg
.NewTitle
);
393 enum NameClashContinuation
{ NOT_HANDLED
, ABORT
, OVERWRITE
, NEW_NAME
, UNKNOWN
};
395 NameClashContinuation
interactiveNameClashResolve(
396 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
397 const OUString
& rTargetURL
,
398 const OUString
& rClashingName
,
399 /* [out] */ uno::Any
& rException
,
400 /* [out] */ OUString
& rNewName
)
402 rtl::Reference
< ucbhelper::SimpleNameClashResolveRequest
> xRequest(
403 new ucbhelper::SimpleNameClashResolveRequest(
404 rTargetURL
, // target folder URL
405 rClashingName
, // clashing name
406 OUString(), // no proposal for new name
407 true /* bSupportsOverwriteData */ ) );
409 rException
= xRequest
->getRequest();
412 uno::Reference
< task::XInteractionHandler
> xIH
413 = xEnv
->getInteractionHandler();
417 xIH
->handle( xRequest
.get() );
419 rtl::Reference
< ucbhelper::InteractionContinuation
>
420 xSelection( xRequest
->getSelection() );
422 if ( xSelection
.is() )
424 // Handler handled the request.
425 uno::Reference
< task::XInteractionAbort
> xAbort(
426 xSelection
.get(), uno::UNO_QUERY
);
435 ucb::XInteractionReplaceExistingData
>
437 xSelection
.get(), uno::UNO_QUERY
);
440 // Try again: Replace existing data.
446 ucb::XInteractionSupplyName
>
448 xSelection
.get(), uno::UNO_QUERY
);
449 if ( xSupplyName
.is() )
451 // Try again: Use new name.
452 rNewName
= xRequest
->getNewName();
457 OSL_FAIL( "Unknown interaction continuation!" );
470 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessor
,
471 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
,
472 const OUString
& rNewTitle
)
473 throw( uno::RuntimeException
)
477 uno::Sequence
< beans::PropertyValue
> aPropValues( 1 );
478 aPropValues
[ 0 ].Name
= "Title";
479 aPropValues
[ 0 ].Handle
= -1;
480 aPropValues
[ 0 ].Value
= uno::makeAny( rNewTitle
);
482 ucb::Command
aSetPropsCommand(
483 OUString( "setPropertyValues" ),
485 uno::makeAny( aPropValues
) );
488 = xCommandProcessor
->execute( aSetPropsCommand
, 0, xEnv
);
490 uno::Sequence
< uno::Any
> aErrors
;
493 OSL_ENSURE( aErrors
.getLength() == 1,
494 "getPropertyValues return value invalid!" );
496 if ( aErrors
[ 0 ].hasValue() )
499 OSL_FAIL( "error setting Title property!" );
503 catch ( uno::RuntimeException
const & )
507 catch ( uno::Exception
const & )
516 uno::Reference
< ucb::XContent
> createNew(
517 const TransferCommandContext
& rContext
,
518 const uno::Reference
< ucb::XContent
> & xTarget
,
519 bool bSourceIsFolder
,
520 bool bSourceIsDocument
,
522 throw( uno::Exception
)
526 // (1) Obtain creatable types from target.
530 // First, try it using "CreatabeleContentsInfo" property and
531 // "createNewContent" command -> the "new" way.
533 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorT(
534 xTarget
, uno::UNO_QUERY
);
535 if ( !xCommandProcessorT
.is() )
538 = uno::makeAny(beans::PropertyValue(
541 uno::makeAny(rContext
.aArg
.TargetURL
),
542 beans::PropertyState_DIRECT_VALUE
));
543 ucbhelper::cancelCommandExecution(
544 ucb::IOErrorCode_CANT_CREATE
,
545 uno::Sequence
< uno::Any
>(&aProps
, 1),
547 OUString("Target is no XCommandProcessor!"),
548 rContext
.xProcessor
);
552 uno::Sequence
< beans::Property
> aPropsToObtain( 1 );
553 aPropsToObtain
[ 0 ].Name
= "CreatableContentsInfo";
554 aPropsToObtain
[ 0 ].Handle
= -1;
556 ucb::Command
aGetPropsCommand(
557 OUString("getPropertyValues"),
559 uno::makeAny( aPropsToObtain
) );
561 uno::Reference
< sdbc::XRow
> xRow
;
562 xCommandProcessorT
->execute( aGetPropsCommand
, 0, rContext
.xEnv
) >>= xRow
;
564 uno::Sequence
< ucb::ContentInfo
> aTypesInfo
;
565 bool bGotTypesInfo
= false;
569 uno::Any aValue
= xRow
->getObject(
570 1, uno::Reference
< container::XNameAccess
>() );
571 if ( aValue
.hasValue() && ( aValue
>>= aTypesInfo
) )
573 bGotTypesInfo
= true;
577 uno::Reference
< ucb::XContentCreator
> xCreator
;
579 if ( !bGotTypesInfo
)
581 // Second, try it using XContentCreator interface -> the "old" way (not
582 // providing the chance to supply an XCommandEnvironment.
584 xCreator
.set( xTarget
, uno::UNO_QUERY
);
586 if ( !xCreator
.is() )
589 = uno::makeAny(beans::PropertyValue(
592 uno::makeAny(rContext
.aArg
.TargetURL
),
593 beans::PropertyState_DIRECT_VALUE
));
594 ucbhelper::cancelCommandExecution(
595 ucb::IOErrorCode_CANT_CREATE
,
596 uno::Sequence
< uno::Any
>(&aProps
, 1),
598 OUString("Target is no XContentCreator!"),
599 rContext
.xProcessor
);
603 aTypesInfo
= xCreator
->queryCreatableContentsInfo();
606 sal_Int32 nCount
= aTypesInfo
.getLength();
610 = uno::makeAny(beans::PropertyValue(
613 uno::makeAny(rContext
.aArg
.TargetURL
),
614 beans::PropertyState_DIRECT_VALUE
));
615 ucbhelper::cancelCommandExecution(
616 ucb::IOErrorCode_CANT_CREATE
,
617 uno::Sequence
< uno::Any
>(&aProps
, 1),
619 OUString("No types creatable!"),
620 rContext
.xProcessor
);
626 // (2) Try to find a matching target type for the source object.
630 uno::Reference
< ucb::XContent
> xNew
;
631 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
633 sal_Int32 nAttribs
= aTypesInfo
[ n
].Attributes
;
636 if ( rContext
.aArg
.Operation
== ucb::TransferCommandOperation_LINK
)
640 if ( nAttribs
& ucb::ContentInfoAttribute::KIND_LINK
)
646 else if ( ( rContext
.aArg
.Operation
647 == ucb::TransferCommandOperation_COPY
) ||
648 ( rContext
.aArg
.Operation
649 == ucb::TransferCommandOperation_MOVE
) )
653 // Is source a link? Create link in target folder then.
656 if ( nAttribs
& ucb::ContentInfoAttribute::KIND_LINK
)
664 // (not a and not b) or (a and b)
665 // not( a or b) or (a and b)
667 if ( ( !!bSourceIsFolder
==
669 & ucb::ContentInfoAttribute::KIND_FOLDER
) )
671 ( !!bSourceIsDocument
==
673 & ucb::ContentInfoAttribute::KIND_DOCUMENT
) )
683 ucbhelper::cancelCommandExecution(
684 uno::makeAny( lang::IllegalArgumentException(
685 OUString( "Unknown transfer operation!" ),
696 // (3) Create a new, empty object of matched type.
700 if ( !xCreator
.is() )
702 // First, try it using "CreatabeleContentsInfo" property and
703 // "createNewContent" command -> the "new" way.
704 ucb::Command
aCreateNewCommand(
705 OUString("createNewContent"),
707 uno::makeAny( aTypesInfo
[ n
] ) );
709 xCommandProcessorT
->execute( aCreateNewCommand
, 0, rContext
.xEnv
)
714 // Second, try it using XContentCreator interface -> the "old"
715 // way (not providing the chance to supply an XCommandEnvironment.
717 xNew
= xCreator
->createNewContent( aTypesInfo
[ n
] );
724 beans::PropertyValue(
727 uno::makeAny(rContext
.aArg
.TargetURL
),
728 beans::PropertyState_DIRECT_VALUE
));
729 ucbhelper::cancelCommandExecution(
730 ucb::IOErrorCode_CANT_CREATE
,
731 uno::Sequence
< uno::Any
>(&aProps
, 1),
733 OUString( "createNewContent failed!" ),
734 rContext
.xProcessor
);
737 break; // escape from 'for' loop
745 void transferProperties(
746 const TransferCommandContext
& rContext
,
747 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
,
748 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorN
)
749 throw( uno::Exception
)
751 ucb::Command
aGetPropertySetInfoCommand(
752 OUString("getPropertySetInfo"),
756 uno::Reference
< beans::XPropertySetInfo
> xInfo
;
757 xCommandProcessorS
->execute( aGetPropertySetInfoCommand
, 0, rContext
.xEnv
)
763 = uno::makeAny(beans::PropertyValue(
766 uno::makeAny(rContext
.aArg
.SourceURL
),
767 beans::PropertyState_DIRECT_VALUE
));
768 ucbhelper::cancelCommandExecution(
769 ucb::IOErrorCode_CANT_READ
,
770 uno::Sequence
< uno::Any
>(&aProps
, 1),
772 OUString( "Unable to get propertyset info from source object!" ),
773 rContext
.xProcessor
);
777 uno::Sequence
< beans::Property
> aAllProps
= xInfo
->getProperties();
779 ucb::Command
aGetPropsCommand1(
780 OUString("getPropertyValues"),
782 uno::makeAny( aAllProps
) );
784 uno::Reference
< sdbc::XRow
> xRow1
;
785 xCommandProcessorS
->execute(
786 aGetPropsCommand1
, 0, rContext
.xEnv
) >>= xRow1
;
791 = uno::makeAny(beans::PropertyValue(
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 OUString( "Unable to get properties from source object!" ),
801 rContext
.xProcessor
);
805 // Assemble data structure for setPropertyValues command.
807 // Note: Make room for additional Title and TargetURL too. -> + 2
808 uno::Sequence
< beans::PropertyValue
> aPropValues(
809 aAllProps
.getLength() + 2 );
811 bool bHasTitle
= rContext
.aArg
.NewTitle
.isEmpty();
812 bool bHasTargetURL
= ( rContext
.aArg
.Operation
813 != ucb::TransferCommandOperation_LINK
);
815 sal_Int32 nWritePos
= 0;
816 for ( sal_Int32 m
= 0; m
< aAllProps
.getLength(); ++m
)
818 const beans::Property
& rCurrProp
= aAllProps
[ m
];
819 beans::PropertyValue
& rCurrValue
= aPropValues
[ nWritePos
];
823 if ( rCurrProp
.Name
== "Title" )
825 // Supply new title, if given.
829 aValue
<<= rContext
.aArg
.NewTitle
;
832 else if ( rCurrProp
.Name
== "TargetURL" )
834 // Supply source URL as link target for the new link to create.
835 if ( !bHasTargetURL
)
837 bHasTargetURL
= true;
838 aValue
<<= rContext
.aArg
.SourceURL
;
842 if ( !aValue
.hasValue() )
846 aValue
= xRow1
->getObject(
847 m
+ 1, uno::Reference
< container::XNameAccess
>() );
849 catch ( sdbc::SQLException
const & )
851 // Argh! But try to bring things to an end. Perhaps the
852 // mad property is not really important...
856 if ( aValue
.hasValue() )
858 rCurrValue
.Name
= rCurrProp
.Name
;
859 rCurrValue
.Handle
= rCurrProp
.Handle
;
860 rCurrValue
.Value
= aValue
;
861 // rCurrValue.State =
867 // Title needed, but not set yet?
868 if ( !bHasTitle
&& !rContext
.aArg
.NewTitle
.isEmpty() )
870 aPropValues
[ nWritePos
].Name
= "Title";
871 aPropValues
[ nWritePos
].Handle
= -1;
872 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.NewTitle
;
877 // TargetURL needed, but not set yet?
878 if ( !bHasTargetURL
&& ( rContext
.aArg
.Operation
879 == ucb::TransferCommandOperation_LINK
) )
881 aPropValues
[ nWritePos
].Name
= "TargetURL";
882 aPropValues
[ nWritePos
].Handle
= -1;
883 aPropValues
[ nWritePos
].Value
<<= rContext
.aArg
.SourceURL
;
888 aPropValues
.realloc( nWritePos
);
890 // Set properties at new object.
892 ucb::Command
aSetPropsCommand(
893 OUString("setPropertyValues"),
895 uno::makeAny( aPropValues
) );
897 xCommandProcessorN
->execute( aSetPropsCommand
, 0, rContext
.xEnv
);
899 // @@@ What to do with source props that are not supported by the
900 // new object? addProperty ???
904 uno::Reference
< io::XInputStream
> getInputStream(
905 const TransferCommandContext
& rContext
,
906 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
907 throw( uno::Exception
)
909 uno::Reference
< io::XInputStream
> xInputStream
;
913 // (1) Try to get data as XInputStream via XActiveDataSink.
919 uno::Reference
< io::XActiveDataSink
> xSink
= new ActiveDataSink
;
921 ucb::OpenCommandArgument2 aArg
;
922 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
923 aArg
.Priority
= 0; // unused
925 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 ); // unused
927 ucb::Command
aOpenCommand(
930 uno::makeAny( aArg
) );
932 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
933 xInputStream
= xSink
->getInputStream();
935 catch ( uno::RuntimeException
const & )
939 catch ( uno::Exception
const & )
941 // will be handled below.
944 if ( !xInputStream
.is() )
948 // (2) Try to get data via XOutputStream.
954 uno::Reference
< io::XOutputStream
> xOutputStream( io::Pipe::create(rContext
.m_xContext
), uno::UNO_QUERY_THROW
);
956 ucb::OpenCommandArgument2 aArg
;
957 aArg
.Mode
= ucb::OpenMode::DOCUMENT
;
958 aArg
.Priority
= 0; // unused
959 aArg
.Sink
= xOutputStream
;
960 aArg
.Properties
= uno::Sequence
< beans::Property
>( 0 );
962 ucb::Command
aOpenCommand(
965 uno::makeAny( aArg
) );
967 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
);
969 xInputStream
= uno::Reference
< io::XInputStream
>(
970 xOutputStream
, uno::UNO_QUERY
);
972 catch ( uno::RuntimeException
const & )
976 catch ( uno::Exception
const & )
978 OSL_FAIL( "unable to get input stream from document!" );
986 uno::Reference
< sdbc::XResultSet
> getResultSet(
987 const TransferCommandContext
& rContext
,
988 const uno::Reference
< ucb::XCommandProcessor
> & xCommandProcessorS
)
989 throw( uno::Exception
)
991 uno::Reference
< sdbc::XResultSet
> xResultSet
;
993 uno::Sequence
< beans::Property
> aProps( 3 );
995 aProps
[ 0 ].Name
= "IsFolder";
996 aProps
[ 0 ].Handle
= -1; /* unknown */
997 aProps
[ 1 ].Name
= "IsDocument";
998 aProps
[ 1 ].Handle
= -1; /* unknown */
999 aProps
[ 2 ].Name
= "TargetURL";
1000 aProps
[ 2 ].Handle
= -1; /* unknown */
1002 ucb::OpenCommandArgument2 aArg
;
1003 aArg
.Mode
= ucb::OpenMode::ALL
;
1004 aArg
.Priority
= 0; // unused
1006 aArg
.Properties
= aProps
;
1008 ucb::Command
aOpenCommand( OUString("open"),
1010 uno::makeAny( aArg
) );
1013 uno::Reference
< ucb::XDynamicResultSet
> xSet
;
1014 xCommandProcessorS
->execute( aOpenCommand
, 0, rContext
.xEnv
) >>= xSet
;
1017 xResultSet
= xSet
->getStaticResultSet();
1019 catch ( uno::RuntimeException
const & )
1023 catch ( uno::Exception
const & )
1025 OSL_FAIL( "unable to get result set from folder!" );
1032 void handleNameClashRename(
1033 const TransferCommandContext
& rContext
,
1034 const uno::Reference
< ucb::XContent
> & xNew
,
1035 const uno::Reference
<
1036 ucb::XCommandProcessor
> & xCommandProcessorN
,
1037 const uno::Reference
<
1038 ucb::XCommandProcessor
> & xCommandProcessorS
,
1039 /* [inout] */ uno::Reference
< io::XInputStream
> & xInputStream
)
1040 throw( uno::Exception
)
1044 // Obtain old title.
1045 uno::Sequence
< beans::Property
> aProps( 1 );
1046 aProps
[ 0 ].Name
= "Title";
1047 aProps
[ 0 ].Handle
= -1;
1049 ucb::Command
aGetPropsCommand(
1050 OUString("getPropertyValues"),
1052 uno::makeAny( aProps
) );
1054 uno::Reference
< sdbc::XRow
> xRow
;
1055 xCommandProcessorN
->execute( aGetPropsCommand
, 0, rContext
.xEnv
) >>= xRow
;
1061 beans::PropertyValue(
1065 xNew
->getIdentifier()->getContentIdentifier() ),
1066 beans::PropertyState_DIRECT_VALUE
) );
1067 ucbhelper::cancelCommandExecution(
1068 ucb::IOErrorCode_CANT_READ
,
1069 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1071 OUString( "Unable to get properties from new object!" ),
1072 rContext
.xProcessor
);
1076 OUString aOldTitle
= xRow
->getString( 1 );
1077 if ( aOldTitle
.isEmpty() )
1079 ucbhelper::cancelCommandExecution(
1080 uno::makeAny( beans::UnknownPropertyException(
1081 OUString( "Unable to get property 'Title' from new object!" ),
1082 rContext
.xProcessor
) ),
1083 rContext
.xOrigEnv
);
1087 // Some pseudo-intelligence for not destroying file extensions.
1088 OUString aOldTitlePre
;
1089 OUString aOldTitlePost
;
1090 sal_Int32 nPos
= aOldTitle
.lastIndexOf( '.' );
1093 aOldTitlePre
= aOldTitle
.copy( 0, nPos
);
1094 aOldTitlePost
= aOldTitle
.copy( nPos
);
1097 aOldTitlePre
= aOldTitle
;
1100 aOldTitlePre
+= "_";
1102 bool bContinue
= true;
1107 OUString aNewTitle
= aOldTitlePre
;
1108 aNewTitle
+= OUString::number( nTry
);
1109 aNewTitle
+= aOldTitlePost
;
1112 setTitle( xCommandProcessorN
, rContext
.xEnv
, aNewTitle
);
1114 // Retry inserting the content.
1117 // Previous try may have read from stream. Seek to begin (if
1118 // optional interface XSeekable is supported) or get a new stream.
1119 if ( xInputStream
.is() )
1121 uno::Reference
< io::XSeekable
> xSeekable(
1122 xInputStream
, uno::UNO_QUERY
);
1123 if ( xSeekable
.is() )
1127 xSeekable
->seek( 0 );
1129 catch ( lang::IllegalArgumentException
const & )
1131 xInputStream
.clear();
1133 catch ( io::IOException
const & )
1135 xInputStream
.clear();
1139 xInputStream
.clear();
1141 if ( !xInputStream
.is() )
1144 = getInputStream( rContext
, xCommandProcessorS
);
1145 if ( !xInputStream
.is() )
1149 beans::PropertyValue(
1153 xNew
->getIdentifier()->
1154 getContentIdentifier() ),
1155 beans::PropertyState_DIRECT_VALUE
) );
1156 ucbhelper::cancelCommandExecution(
1157 ucb::IOErrorCode_CANT_READ
,
1158 uno::Sequence
< uno::Any
>( &aProps2
, 1 ),
1160 OUString( "Got no data stream from source!" ),
1161 rContext
.xProcessor
);
1167 ucb::InsertCommandArgument2 aArg
;
1168 aArg
.Data
= xInputStream
;
1169 aArg
.ReplaceExisting
= sal_False
;
1171 ucb::Command
aInsertCommand(
1174 uno::makeAny( aArg
) );
1176 xCommandProcessorN
->execute( aInsertCommand
, 0, rContext
.xEnv
);
1181 catch ( uno::RuntimeException
const & )
1185 catch ( uno::Exception
const & )
1189 while ( bContinue
&& ( nTry
< 50 ) );
1193 ucbhelper::cancelCommandExecution(
1195 ucb::UnsupportedNameClashException(
1196 OUString( "Unable to resolve name clash!" ),
1197 rContext
.xProcessor
,
1198 ucb::NameClash::RENAME
) ),
1199 rContext
.xOrigEnv
);
1205 void globalTransfer_(
1206 const TransferCommandContext
& rContext
,
1207 const uno::Reference
< ucb::XContent
> & xSource
,
1208 const uno::Reference
< ucb::XContent
> & xTarget
,
1209 const uno::Reference
< sdbc::XRow
> & xSourceProps
)
1210 throw( uno::Exception
)
1212 // IsFolder: property is required.
1213 bool bSourceIsFolder
= xSourceProps
->getBoolean( 1 );
1214 if ( !bSourceIsFolder
&& xSourceProps
->wasNull() )
1216 ucbhelper::cancelCommandExecution(
1217 uno::makeAny( beans::UnknownPropertyException(
1218 OUString( "Unable to get property 'IsFolder' "
1219 "from source object!" ),
1220 rContext
.xProcessor
) ),
1221 rContext
.xOrigEnv
);
1225 // IsDocument: property is required.
1226 bool bSourceIsDocument
= xSourceProps
->getBoolean( 2 );
1227 if ( !bSourceIsDocument
&& xSourceProps
->wasNull() )
1229 ucbhelper::cancelCommandExecution(
1230 uno::makeAny( beans::UnknownPropertyException(
1231 OUString( "Unable to get property 'IsDocument' "
1232 "from source object!" ),
1233 rContext
.xProcessor
) ),
1234 rContext
.xOrigEnv
);
1238 // TargetURL: property is optional.
1239 bool bSourceIsLink
= !xSourceProps
->getString( 3 ).isEmpty();
1243 // (1) Try to find a matching target type for the source object and
1244 // create a new, empty object of that type.
1248 uno::Reference
< ucb::XContent
> xNew
= createNew( rContext
,
1256 = uno::makeAny(beans::PropertyValue(
1257 OUString( "Folder"),
1259 uno::makeAny(rContext
.aArg
.TargetURL
),
1260 beans::PropertyState_DIRECT_VALUE
));
1261 ucbhelper::cancelCommandExecution(
1262 ucb::IOErrorCode_CANT_CREATE
,
1263 uno::Sequence
< uno::Any
>(&aProps
, 1),
1265 OUString( "No matching content type at target!" ),
1266 rContext
.xProcessor
);
1272 // (2) Transfer property values from source to new object.
1276 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorN(
1277 xNew
, uno::UNO_QUERY
);
1278 if ( !xCommandProcessorN
.is() )
1281 = uno::makeAny(beans::PropertyValue(
1285 xNew
->getIdentifier()->
1286 getContentIdentifier()),
1287 beans::PropertyState_DIRECT_VALUE
));
1288 ucbhelper::cancelCommandExecution(
1289 ucb::IOErrorCode_CANT_WRITE
,
1290 uno::Sequence
< uno::Any
>(&aProps
, 1),
1292 OUString( "New content is not a XCommandProcessor!" ),
1293 rContext
.xProcessor
);
1297 // Obtain all properties from source.
1299 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessorS(
1300 xSource
, uno::UNO_QUERY
);
1301 if ( !xCommandProcessorS
.is() )
1304 = uno::makeAny(beans::PropertyValue(
1307 uno::makeAny(rContext
.aArg
.SourceURL
),
1308 beans::PropertyState_DIRECT_VALUE
));
1309 ucbhelper::cancelCommandExecution(
1310 ucb::IOErrorCode_CANT_READ
,
1311 uno::Sequence
< uno::Any
>(&aProps
, 1),
1313 OUString( "Source content is not a XCommandProcessor!" ),
1314 rContext
.xProcessor
);
1318 transferProperties( rContext
, xCommandProcessorS
, xCommandProcessorN
);
1322 // (3) Try to obtain a data stream from source.
1326 uno::Reference
< io::XInputStream
> xInputStream
;
1328 if ( bSourceIsDocument
&& ( rContext
.aArg
.Operation
1329 != ucb::TransferCommandOperation_LINK
) )
1330 xInputStream
= getInputStream( rContext
, xCommandProcessorS
);
1334 // (4) Try to obtain a resultset (children) from source.
1338 uno::Reference
< sdbc::XResultSet
> xResultSet
;
1340 if ( bSourceIsFolder
&& ( rContext
.aArg
.Operation
1341 != ucb::TransferCommandOperation_LINK
) )
1342 xResultSet
= getResultSet( rContext
, xCommandProcessorS
);
1346 // (5) Insert (store) new content.
1350 ucb::InsertCommandArgument2 aArg
;
1351 aArg
.Data
= xInputStream
;
1352 aArg
.MimeType
= rContext
.aArg
.MimeType
;
1353 aArg
.DocumentId
= rContext
.aArg
.DocumentId
;
1355 switch ( rContext
.aArg
.NameClash
)
1357 case ucb::NameClash::OVERWRITE
:
1358 aArg
.ReplaceExisting
= sal_True
;
1361 case ucb::NameClash::ERROR
:
1362 case ucb::NameClash::RENAME
:
1363 case ucb::NameClash::KEEP
: // deprecated
1364 case ucb::NameClash::ASK
:
1365 aArg
.ReplaceExisting
= sal_False
;
1369 aArg
.ReplaceExisting
= sal_False
;
1370 OSL_FAIL( "Unknown nameclash directive!" );
1374 OUString aDesiredName
= createDesiredName( rContext
.aArg
);
1383 ucb::Command
aInsertCommand(
1386 uno::makeAny( aArg
) );
1388 xCommandProcessorN
->execute( aInsertCommand
, 0, rContext
.xEnv
);
1390 catch ( ucb::UnsupportedNameClashException
const & exc
)
1392 OSL_ENSURE( !aArg
.ReplaceExisting
,
1393 "BUG: UnsupportedNameClashException not allowed here!" );
1395 if (exc
.NameClash
!= ucb::NameClash::ERROR
) {
1396 OSL_FAIL( "BUG: NameClash::ERROR expected!" );
1399 // No chance to solve name clashes, because I'm not able to detect
1400 // whether there is one.
1401 throw ucb::UnsupportedNameClashException(
1403 "Unable to resolve name clashes, no chance to detect "
1404 "that there is one!" ),
1405 rContext
.xProcessor
,
1406 rContext
.aArg
.NameClash
);
1408 catch ( ucb::NameClashException
const & )
1410 // The 'insert' command throws a NameClashException if the parameter
1411 // ReplaceExisting of the command's argument was set to false and
1412 // there exists a resource with a clashing name in the target folder
1413 // of the operation.
1415 // 'insert' command has no direct support for name clashes other
1416 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1417 // ( ReplaceExisting == true ). So we have to implement the
1418 // other name clash handling directives on top of the content.
1420 // @@@ 'insert' command should be extended that it accepts a
1421 // name clash handling directive, exactly like 'transfer' command.
1423 switch ( rContext
.aArg
.NameClash
)
1425 case ucb::NameClash::OVERWRITE
:
1427 ucbhelper::cancelCommandExecution(
1429 ucb::UnsupportedNameClashException(
1431 "BUG: insert + replace == true MUST NOT "
1432 "throw NameClashException." ),
1433 rContext
.xProcessor
,
1434 rContext
.aArg
.NameClash
) ),
1435 rContext
.xOrigEnv
);
1439 case ucb::NameClash::ERROR
:
1442 case ucb::NameClash::RENAME
:
1444 // "invent" a new valid title.
1445 handleNameClashRename( rContext
,
1453 case ucb::NameClash::ASK
:
1457 NameClashContinuation eCont
1458 = interactiveNameClashResolve(
1459 rContext
.xOrigEnv
, // always use original environment!
1460 rContext
.aArg
.TargetURL
, // target folder URL
1469 cppu::throwException( aExc
);
1473 // Handled, but not clear, how...
1474 // fall through intended.
1477 throw ucb::CommandFailedException(
1479 "abort requested via interaction "
1481 uno::Reference
< uno::XInterface
>(),
1486 OSL_ENSURE( aArg
.ReplaceExisting
== sal_False
,
1487 "Hu? ReplaceExisting already true?"
1489 aArg
.ReplaceExisting
= sal_True
;
1495 // set new name -> set "Title" property...
1496 if ( setTitle( xCommandProcessorN
,
1500 // remember suggested title...
1501 aDesiredName
= aNewTitle
;
1503 // ... and try again.
1508 // error setting title. Abort.
1509 throw ucb::CommandFailedException(
1510 OUString( "error setting Title property!" ),
1511 uno::Reference
< uno::XInterface
>(),
1518 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1522 case ucb::NameClash::KEEP
: // deprecated
1525 ucbhelper::cancelCommandExecution(
1527 ucb::UnsupportedNameClashException(
1529 "default action, don't know how to "
1530 "handle name clash" ),
1531 rContext
.xProcessor
,
1532 rContext
.aArg
.NameClash
) ),
1533 rContext
.xOrigEnv
);
1543 // (6) Process children of source.
1547 if ( xResultSet
.is() )
1551 // Iterate over children...
1553 uno::Reference
< sdbc::XRow
> xChildRow(
1554 xResultSet
, uno::UNO_QUERY
);
1556 if ( !xChildRow
.is() )
1560 beans::PropertyValue(
1563 uno::makeAny(rContext
.aArg
.SourceURL
),
1564 beans::PropertyState_DIRECT_VALUE
));
1565 ucbhelper::cancelCommandExecution(
1566 ucb::IOErrorCode_CANT_READ
,
1567 uno::Sequence
< uno::Any
>(&aProps
, 1),
1569 OUString( "Unable to get properties from children of source!" ),
1570 rContext
.xProcessor
);
1574 uno::Reference
< ucb::XContentAccess
> xChildAccess(
1575 xResultSet
, uno::UNO_QUERY
);
1577 if ( !xChildAccess
.is() )
1581 beans::PropertyValue(
1584 uno::makeAny(rContext
.aArg
.SourceURL
),
1585 beans::PropertyState_DIRECT_VALUE
));
1586 ucbhelper::cancelCommandExecution(
1587 ucb::IOErrorCode_CANT_READ
,
1588 uno::Sequence
< uno::Any
>(&aProps
, 1),
1590 OUString( "Unable to get children of source!" ),
1591 rContext
.xProcessor
);
1595 if ( xResultSet
->first() )
1597 ucb::GlobalTransferCommandArgument2
aTransArg(
1598 rContext
.aArg
.Operation
,
1599 OUString(), // SourceURL; filled later
1600 xNew
->getIdentifier()
1601 ->getContentIdentifier(), // TargetURL
1602 OUString(), // NewTitle;
1603 rContext
.aArg
.NameClash
,
1604 rContext
.aArg
.MimeType
,
1605 rContext
.aArg
.DocumentId
);
1607 TransferCommandContext
aSubCtx(
1608 rContext
.m_xContext
,
1609 rContext
.xProcessor
,
1615 uno::Reference
< ucb::XContent
> xChild
1616 = xChildAccess
->queryContent();
1621 aSubCtx
.aArg
.SourceURL
1622 = xChild
->getIdentifier()->getContentIdentifier();
1624 globalTransfer_( aSubCtx
,
1630 while ( xResultSet
->next() );
1633 catch ( sdbc::SQLException
const & )
1639 uno::Reference
< ucb::XCommandProcessor
> xcp(
1640 xTarget
, uno::UNO_QUERY
);
1643 uno::Reference
< ucb::XCommandInfo
> xci
;
1648 OUString("getCommandInfo"),
1654 const OUString
cmdName("flush");
1655 if((aAny
>>= xci
) && xci
->hasCommandByName(cmdName
))
1664 catch( uno::Exception
const & )
1673 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1677 uno::Reference
< ucb::XCommandInfo
>
1678 UniversalContentBroker::getCommandInfo()
1680 return uno::Reference
< ucb::XCommandInfo
>( new CommandProcessorInfo() );
1684 void UniversalContentBroker::globalTransfer(
1685 const ucb::GlobalTransferCommandArgument2
& rArg
,
1686 const uno::Reference
< ucb::XCommandEnvironment
> & xEnv
)
1687 throw( uno::Exception
)
1689 // Use own command environment with own interaction handler intercepting
1690 // some interaction requests that shall not be handled by the user-supplied
1691 // interaction handler.
1692 uno::Reference
< ucb::XCommandEnvironment
> xLocalEnv
;
1695 xLocalEnv
.set( ucb::CommandEnvironment::create(
1697 new InteractionHandlerProxy( xEnv
->getInteractionHandler() ),
1698 xEnv
->getProgressHandler() ) );
1703 // (1) Try to transfer the content using 'transfer' command.
1707 uno::Reference
< ucb::XContent
> xTarget
;
1708 uno::Reference
< ucb::XContentIdentifier
> xId
1709 = createContentIdentifier( rArg
.TargetURL
);
1714 xTarget
= queryContent( xId
);
1716 catch ( ucb::IllegalIdentifierException
const & )
1721 if ( !xTarget
.is() )
1724 = uno::makeAny(beans::PropertyValue(
1727 uno::makeAny(rArg
.TargetURL
),
1728 beans::PropertyState_DIRECT_VALUE
));
1729 ucbhelper::cancelCommandExecution(
1730 ucb::IOErrorCode_CANT_READ
,
1731 uno::Sequence
< uno::Any
>(&aProps
, 1),
1733 OUString( "Can't instanciate target object!" ),
1738 if ( ( rArg
.Operation
== ucb::TransferCommandOperation_COPY
) ||
1739 ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
) )
1741 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1742 xTarget
, uno::UNO_QUERY
);
1743 if ( !xCommandProcessor
.is() )
1747 beans::PropertyValue(
1750 uno::makeAny(rArg
.TargetURL
),
1751 beans::PropertyState_DIRECT_VALUE
));
1752 ucbhelper::cancelCommandExecution(
1753 ucb::IOErrorCode_CANT_READ
,
1754 uno::Sequence
< uno::Any
>(&aProps
, 1),
1756 OUString( "Target content is not a XCommandProcessor!" ),
1761 ucb::TransferInfo2
aTransferArg(
1763 == ucb::TransferCommandOperation_MOVE
), // MoveData
1776 ucb::Command
aCommand(
1777 OUString( "transfer" ), // Name
1779 uno::makeAny( aTransferArg
) ); // Argument
1781 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
1783 // Command succeeded. We're done.
1786 catch ( ucb::InteractiveBadTransferURLException
const & )
1788 // Source URL is not supported by target. Try to transfer
1789 // the content "manually".
1791 catch ( ucb::UnsupportedCommandException
const & )
1793 // 'transfer' command is not supported by commandprocessor.
1794 // Try to transfer manually.
1796 catch ( ucb::UnsupportedNameClashException
const & exc
)
1798 OSL_ENSURE( aTransferArg
.NameClash
== exc
.NameClash
,
1799 "nameclash mismatch!" );
1800 if ( exc
.NameClash
== ucb::NameClash::ASK
)
1802 // Try to detect a name clash by invoking "transfer" with
1803 // NameClash::ERROR.
1806 ucb::TransferInfo2
aTransferArg1(
1807 aTransferArg
.MoveData
,
1808 aTransferArg
.SourceURL
,
1809 aTransferArg
.NewTitle
,
1810 ucb::NameClash::ERROR
,
1811 aTransferArg
.MimeType
);
1813 ucb::Command
aCommand1(
1814 OUString("transfer"),
1816 uno::makeAny( aTransferArg1
) );
1818 xCommandProcessor
->execute( aCommand1
, 0, xLocalEnv
);
1820 // Command succeeded. We're done.
1823 catch ( ucb::UnsupportedNameClashException
const & )
1825 // No chance to solve name clashes, because I'm not
1826 // able to detect whether there is one.
1827 throw exc
; // Not just 'throw;'!
1829 catch ( ucb::NameClashException
const & )
1831 // There's a clash. Use interaction handler to solve it.
1835 NameClashContinuation eCont
1836 = interactiveNameClashResolve(
1837 xEnv
, // always use original environment!
1838 rArg
.TargetURL
, // target folder URL
1840 aTransferArg
), // clashing name
1848 cppu::throwException( aExc
);
1852 // Handled, but not clear, how...
1853 // fall through intended.
1856 throw ucb::CommandFailedException(
1858 "abort requested via interaction "
1860 uno::Reference
< uno::XInterface
>(),
1865 aTransferArg
.NameClash
1866 = ucb::NameClash::OVERWRITE
;
1871 aTransferArg
.NewTitle
= aNewTitle
;
1876 OSL_ENSURE( bRetry
, "bRetry must be true here!!!" );
1890 // (2) Try to transfer the content "manually".
1894 uno::Reference
< ucb::XContent
> xSource
;
1897 uno::Reference
< ucb::XContentIdentifier
> xId2
1898 = createContentIdentifier( rArg
.SourceURL
);
1900 xSource
= queryContent( xId2
);
1902 catch ( ucb::IllegalIdentifierException
const & )
1904 // Error handling via "if ( !xSource.is() )" below.
1907 if ( !xSource
.is() )
1910 = uno::makeAny(beans::PropertyValue(
1913 uno::makeAny(rArg
.SourceURL
),
1914 beans::PropertyState_DIRECT_VALUE
));
1915 ucbhelper::cancelCommandExecution(
1916 ucb::IOErrorCode_CANT_READ
,
1917 uno::Sequence
< uno::Any
>(&aProps
, 1),
1919 OUString( "Can't instanciate source object!" ),
1924 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
1925 xSource
, uno::UNO_QUERY
);
1926 if ( !xCommandProcessor
.is() )
1929 = uno::makeAny(beans::PropertyValue(
1932 uno::makeAny(rArg
.SourceURL
),
1933 beans::PropertyState_DIRECT_VALUE
));
1934 ucbhelper::cancelCommandExecution(
1935 ucb::IOErrorCode_CANT_READ
,
1936 uno::Sequence
< uno::Any
>(&aProps
, 1),
1938 OUString( "Source content is not a XCommandProcessor!" ),
1943 // Obtain interesting property values from source...
1945 uno::Sequence
< beans::Property
> aProps( 4 );
1947 aProps
[ 0 ].Name
= "IsFolder";
1948 aProps
[ 0 ].Handle
= -1; /* unknown */
1949 aProps
[ 1 ].Name
= "IsDocument";
1950 aProps
[ 1 ].Handle
= -1; /* unknown */
1951 aProps
[ 2 ].Name
= "TargetURL";
1952 aProps
[ 2 ].Handle
= -1; /* unknown */
1953 aProps
[ 3 ].Name
= "BaseURI";
1954 aProps
[ 3 ].Handle
= -1; /* unknown */
1956 ucb::Command
aGetPropsCommand(
1957 OUString("getPropertyValues"),
1959 uno::makeAny( aProps
) );
1961 uno::Reference
< sdbc::XRow
> xRow
;
1962 xCommandProcessor
->execute( aGetPropsCommand
, 0, xLocalEnv
) >>= xRow
;
1967 = uno::makeAny(beans::PropertyValue(
1970 uno::makeAny(rArg
.SourceURL
),
1971 beans::PropertyState_DIRECT_VALUE
));
1972 ucbhelper::cancelCommandExecution(
1973 ucb::IOErrorCode_CANT_READ
,
1974 uno::Sequence
< uno::Any
>(&aProps2
, 1),
1976 OUString( "Unable to get properties from source object!" ),
1981 TransferCommandContext
aTransferCtx(
1982 m_xContext
, this, xLocalEnv
, xEnv
, rArg
);
1984 if ( rArg
.NewTitle
.isEmpty() )
1986 // BaseURI: property is optional.
1987 OUString
aBaseURI( xRow
->getString( 4 ) );
1988 if ( !aBaseURI
.isEmpty() )
1990 aTransferCtx
.aArg
.NewTitle
1991 = createDesiredName( aBaseURI
, OUString() );
1996 globalTransfer_( aTransferCtx
, xSource
, xTarget
, xRow
);
2000 // (3) Delete source, if operation is MOVE.
2004 if ( rArg
.Operation
== ucb::TransferCommandOperation_MOVE
)
2008 ucb::Command
aCommand(
2009 OUString("delete"), // Name
2011 uno::makeAny( true ) ); // Argument
2013 xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
2015 catch ( uno::Exception
const & )
2017 OSL_FAIL( "Cannot delete source object!" );
2023 uno::Any
UniversalContentBroker::checkIn( const ucb::CheckinArgument
& rArg
,
2024 const uno::Reference
< ucb::XCommandEnvironment
>& xEnv
) throw ( uno::Exception
)
2027 // Use own command environment with own interaction handler intercepting
2028 // some interaction requests that shall not be handled by the user-supplied
2029 // interaction handler.
2030 uno::Reference
< ucb::XCommandEnvironment
> xLocalEnv
;
2033 xLocalEnv
.set( ucb::CommandEnvironment::create(
2035 new InteractionHandlerProxy( xEnv
->getInteractionHandler() ),
2036 xEnv
->getProgressHandler() ) );
2039 uno::Reference
< ucb::XContent
> xTarget
;
2040 uno::Reference
< ucb::XContentIdentifier
> xId
2041 = createContentIdentifier( rArg
.TargetURL
);
2046 xTarget
= queryContent( xId
);
2048 catch ( ucb::IllegalIdentifierException
const & )
2053 if ( !xTarget
.is() )
2056 = uno::makeAny(beans::PropertyValue(
2057 OUString( "Uri" ), -1,
2058 uno::makeAny( rArg
.TargetURL
),
2059 beans::PropertyState_DIRECT_VALUE
) );
2060 ucbhelper::cancelCommandExecution(
2061 ucb::IOErrorCode_CANT_READ
,
2062 uno::Sequence
< uno::Any
>( &aProps
, 1 ),
2064 OUString( "Can't instanciate target object!" ),
2069 uno::Reference
< ucb::XCommandProcessor
> xCommandProcessor(
2070 xTarget
, uno::UNO_QUERY
);
2071 if ( !xCommandProcessor
.is() )
2075 beans::PropertyValue(
2076 OUString( "Uri" ), -1,
2077 uno::makeAny( rArg
.TargetURL
),
2078 beans::PropertyState_DIRECT_VALUE
) );
2079 ucbhelper::cancelCommandExecution(
2080 ucb::IOErrorCode_CANT_READ
,
2081 uno::Sequence
< uno::Any
>( &aProps
, 1 ),
2083 OUString( "Target content is not a XCommandProcessor!" ),
2090 ucb::Command
aCommand(
2091 OUString( "checkin" ), -1,
2092 uno::makeAny( rArg
) );
2094 aRet
= xCommandProcessor
->execute( aCommand
, 0, xLocalEnv
);
2096 catch ( ucb::UnsupportedCommandException
const & )
2098 // 'checkin' command is not supported by commandprocessor:
2104 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */