1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_ucb.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32 #include <osl/diagnose.h>
33 #include <cppuhelper/implbase1.hxx>
34 #include <cppuhelper/exc_hlp.hxx>
35 #include <rtl/ustring.h>
36 #include <rtl/ustring.hxx>
37 #include <com/sun/star/uno/XInterface.hpp>
38 #include <com/sun/star/beans/PropertyState.hpp>
39 #include <com/sun/star/beans/PropertyValue.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/container/XChild.hpp>
42 #include <com/sun/star/beans/XPropertySetInfo.hpp>
43 #include <com/sun/star/io/XActiveDataSink.hpp>
44 #include <com/sun/star/io/XOutputStream.hpp>
45 #include <com/sun/star/io/XSeekable.hpp>
46 #include <com/sun/star/sdbc/XRow.hpp>
47 #include <com/sun/star/task/XInteractionHandler.hpp>
48 #include <com/sun/star/ucb/CommandEnvironment.hpp>
49 #include <com/sun/star/ucb/CommandFailedException.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/ucb/GlobalTransferCommandArgument.hpp>
52 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
53 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
54 #include <com/sun/star/ucb/NameClash.hpp>
55 #include <com/sun/star/ucb/NameClashException.hpp>
56 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
57 #include <com/sun/star/ucb/OpenMode.hpp>
58 #include <com/sun/star/ucb/TransferInfo.hpp>
59 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
60 #include <com/sun/star/ucb/XCommandInfo.hpp>
61 #include <com/sun/star/ucb/XContentAccess.hpp>
62 #include <com/sun/star/ucb/XContentCreator.hpp>
63 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
64 #include <com/sun/star/uno/Any.hxx>
65 #include <com/sun/star/uno/Sequence.hxx>
66 #include <ucbhelper/cancelcommandexecution.hxx>
67 #include <ucbhelper/simplenameclashresolverequest.hxx>
68 #include "ucbcmds.hxx"
69 #include "ucb.hxx"
70
71 using namespace com::sun::star;
72
73 namespace
74 {
75
76 //=========================================================================
77 //
78 // struct TransferCommandContext.
79 //
80 //=========================================================================
81
82 struct TransferCommandContext
83 {
84 uno::Reference< lang::XMultiServiceFactory > xSMgr;
85 uno::Reference< ucb::XCommandProcessor > xProcessor;
86 uno::Reference< ucb::XCommandEnvironment > xEnv;
87 uno::Reference< ucb::XCommandEnvironment > xOrigEnv;
88 ucb::GlobalTransferCommandArgument aArg;
89
TransferCommandContext__anon9eb7a7f90111::TransferCommandContext90 TransferCommandContext(
91 const uno::Reference< lang::XMultiServiceFactory > & rxSMgr,
92 const uno::Reference< ucb::XCommandProcessor > & rxProcessor,
93 const uno::Reference< ucb::XCommandEnvironment > & rxEnv,
94 const uno::Reference< ucb::XCommandEnvironment > & rxOrigEnv,
95 const ucb::GlobalTransferCommandArgument & rArg )
96 : xSMgr( rxSMgr ), xProcessor( rxProcessor ), xEnv( rxEnv ),
97 xOrigEnv( rxOrigEnv ), aArg( rArg ) {}
98 };
99
100 //=========================================================================
101 //
102 // class InteractionHandlerProxy.
103 //
104 //=========================================================================
105
106 class InteractionHandlerProxy :
107 public cppu::WeakImplHelper1< task::XInteractionHandler >
108 {
109 uno::Reference< task::XInteractionHandler > m_xOrig;
110
111 public:
InteractionHandlerProxy(const uno::Reference<task::XInteractionHandler> & xOrig)112 InteractionHandlerProxy(
113 const uno::Reference< task::XInteractionHandler > & xOrig )
114 : m_xOrig( xOrig ) {}
115
116 // XInteractionHandler methods.
117 virtual void SAL_CALL handle(
118 const uno::Reference< task::XInteractionRequest >& Request );
119 };
120
121 //=========================================================================
122 // virtual
handle(const uno::Reference<task::XInteractionRequest> & Request)123 void SAL_CALL InteractionHandlerProxy::handle(
124 const uno::Reference< task::XInteractionRequest >& Request )
125 {
126 if ( !m_xOrig.is() )
127 return;
128
129 // Filter unwanted requests by just not handling them.
130 uno::Any aRequest = Request->getRequest();
131
132 // "transfer"
133 ucb::InteractiveBadTransferURLException aBadTransferURLEx;
134 if ( aRequest >>= aBadTransferURLEx )
135 {
136 return;
137 }
138 else
139 {
140 // "transfer"
141 ucb::UnsupportedNameClashException aUnsupportedNameClashEx;
142 if ( aRequest >>= aUnsupportedNameClashEx )
143 {
144 if ( aUnsupportedNameClashEx.NameClash
145 != ucb::NameClash::ERROR )
146 return;
147 }
148 else
149 {
150 // "insert"
151 ucb::NameClashException aNameClashEx;
152 if ( aRequest >>= aNameClashEx )
153 {
154 return;
155 }
156 else
157 {
158 // "transfer"
159 ucb::UnsupportedCommandException aUnsupportedCommandEx;
160 if ( aRequest >>= aUnsupportedCommandEx )
161 {
162 return;
163 }
164 }
165 }
166 }
167
168 // not filtered; let the original handler do the work.
169 m_xOrig->handle( Request );
170 }
171
172 //=========================================================================
173 //
174 // class ActiveDataSink.
175 //
176 //=========================================================================
177
178 class ActiveDataSink : public cppu::WeakImplHelper1< io::XActiveDataSink >
179 {
180 uno::Reference< io::XInputStream > m_xStream;
181
182 public:
183 // XActiveDataSink methods.
184 virtual void SAL_CALL setInputStream(
185 const uno::Reference< io::XInputStream >& aStream );
186 virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream();
187 };
188
189 //=========================================================================
190 // virtual
setInputStream(const uno::Reference<io::XInputStream> & aStream)191 void SAL_CALL ActiveDataSink::setInputStream(
192 const uno::Reference< io::XInputStream >& aStream )
193 {
194 m_xStream = aStream;
195 }
196
197 //=========================================================================
198 // virtual
getInputStream()199 uno::Reference< io::XInputStream > SAL_CALL ActiveDataSink::getInputStream()
200 {
201 return m_xStream;
202 }
203
204 //=========================================================================
205 //
206 // class CommandProcessorInfo.
207 //
208 //=========================================================================
209
210 class CommandProcessorInfo :
211 public cppu::WeakImplHelper1< ucb::XCommandInfo >
212 {
213 uno::Sequence< ucb::CommandInfo > * m_pInfo;
214
215 public:
216 CommandProcessorInfo();
217 virtual ~CommandProcessorInfo();
218
219 // XCommandInfo methods
220 virtual uno::Sequence< ucb::CommandInfo > SAL_CALL getCommands();
221 virtual ucb::CommandInfo SAL_CALL
222 getCommandInfoByName( const rtl::OUString& Name );
223 virtual ucb::CommandInfo SAL_CALL
224 getCommandInfoByHandle( sal_Int32 Handle );
225 virtual sal_Bool SAL_CALL hasCommandByName( const rtl::OUString& Name );
226 virtual sal_Bool SAL_CALL hasCommandByHandle( sal_Int32 Handle );
227 };
228
229 //=========================================================================
CommandProcessorInfo()230 CommandProcessorInfo::CommandProcessorInfo()
231 {
232 m_pInfo = new uno::Sequence< ucb::CommandInfo >( 2 );
233
234 (*m_pInfo)[ 0 ]
235 = ucb::CommandInfo(
236 rtl::OUString::createFromAscii( GETCOMMANDINFO_NAME ), // Name
237 GETCOMMANDINFO_HANDLE, // Handle
238 getCppuVoidType() ); // ArgType
239 (*m_pInfo)[ 1 ]
240 = ucb::CommandInfo(
241 rtl::OUString::createFromAscii( GLOBALTRANSFER_NAME ), // Name
242 GLOBALTRANSFER_HANDLE, // Handle
243 getCppuType(
244 static_cast<
245 ucb::GlobalTransferCommandArgument * >( 0 ) ) ); // ArgType
246 }
247
248 //=========================================================================
249 // virtual
~CommandProcessorInfo()250 CommandProcessorInfo::~CommandProcessorInfo()
251 {
252 delete m_pInfo;
253 }
254
255 //=========================================================================
256 // virtual
257 uno::Sequence< ucb::CommandInfo > SAL_CALL
getCommands()258 CommandProcessorInfo::getCommands()
259 {
260 return uno::Sequence< ucb::CommandInfo >( *m_pInfo );
261 }
262
263 //=========================================================================
264 // virtual
265 ucb::CommandInfo SAL_CALL
getCommandInfoByName(const rtl::OUString & Name)266 CommandProcessorInfo::getCommandInfoByName( const rtl::OUString& Name )
267 {
268 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
269 {
270 if ( (*m_pInfo)[ n ].Name == Name )
271 return ucb::CommandInfo( (*m_pInfo)[ n ] );
272 }
273
274 throw ucb::UnsupportedCommandException();
275 }
276
277 //=========================================================================
278 // virtual
279 ucb::CommandInfo SAL_CALL
getCommandInfoByHandle(sal_Int32 Handle)280 CommandProcessorInfo::getCommandInfoByHandle( sal_Int32 Handle )
281 {
282 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
283 {
284 if ( (*m_pInfo)[ n ].Handle == Handle )
285 return ucb::CommandInfo( (*m_pInfo)[ n ] );
286 }
287
288 throw ucb::UnsupportedCommandException();
289 }
290
291 //=========================================================================
292 // virtual
hasCommandByName(const rtl::OUString & Name)293 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByName(
294 const rtl::OUString& Name )
295 {
296 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
297 {
298 if ( (*m_pInfo)[ n ].Name == Name )
299 return sal_True;
300 }
301
302 return sal_False;
303 }
304
305 //=========================================================================
306 // virtual
hasCommandByHandle(sal_Int32 Handle)307 sal_Bool SAL_CALL CommandProcessorInfo::hasCommandByHandle( sal_Int32 Handle )
308 {
309 for ( sal_Int32 n = 0; n < m_pInfo->getLength(); ++n )
310 {
311 if ( (*m_pInfo)[ n ].Handle == Handle )
312 return sal_True;
313 }
314
315 return sal_False;
316 }
317
318 //=========================================================================
319 //=========================================================================
320 //=========================================================================
321
createDesiredName(const rtl::OUString & rSourceURL,const rtl::OUString & rNewTitle)322 rtl::OUString createDesiredName(
323 const rtl::OUString & rSourceURL, const rtl::OUString & rNewTitle )
324 {
325 rtl::OUString aName( rNewTitle );
326 if ( aName.getLength() == 0 )
327 {
328 // calculate name using source URL
329
330 // @@@ It's not guaranteed that slashes contained in the URL are
331 // actually path separators. This depends on the fact whether the
332 // URL is hierarchical. Only then the slashes are path separators.
333 // Therefore this algorithm is not guaranteed to work! But, ATM
334 // I don't know a better solution. It would have been better to
335 // have a member for the clashing name in
336 // UnsupportedNameClashException...
337
338 sal_Int32 nLastSlash = rSourceURL.lastIndexOf( '/' );
339 bool bTrailingSlash = false;
340 if ( nLastSlash == rSourceURL.getLength() - 1 )
341 {
342 nLastSlash = rSourceURL.lastIndexOf( '/', nLastSlash );
343 bTrailingSlash = true;
344 }
345
346 if ( nLastSlash != -1 )
347 {
348 if ( bTrailingSlash )
349 aName = rSourceURL.copy(
350 nLastSlash + 1,
351 rSourceURL.getLength() - nLastSlash - 2 );
352 else
353 aName = rSourceURL.copy( nLastSlash + 1 );
354 }
355 else
356 {
357 aName = rSourceURL;
358 }
359
360 // query, fragment present?
361 sal_Int32 nPos = aName.indexOf( '?' );
362 if ( nPos == -1 )
363 nPos = aName.indexOf( '#' );
364
365 if ( nPos != -1 )
366 aName = aName.copy( 0, nPos );
367 }
368 return rtl::OUString( aName );
369 }
370
createDesiredName(const ucb::GlobalTransferCommandArgument & rArg)371 rtl::OUString createDesiredName(
372 const ucb::GlobalTransferCommandArgument & rArg )
373 {
374 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
375 }
376
createDesiredName(const ucb::TransferInfo & rArg)377 rtl::OUString createDesiredName(
378 const ucb::TransferInfo & rArg )
379 {
380 return createDesiredName( rArg.SourceURL, rArg.NewTitle );
381 }
382
383 //=========================================================================
384 enum NameClashContinuation { NOT_HANDLED, ABORT, OVERWRITE, NEW_NAME, UNKNOWN };
385
interactiveNameClashResolve(const uno::Reference<ucb::XCommandEnvironment> & xEnv,const rtl::OUString & rTargetURL,const rtl::OUString & rClashingName,uno::Any & rException,rtl::OUString & rNewName)386 NameClashContinuation interactiveNameClashResolve(
387 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
388 const rtl::OUString & rTargetURL,
389 const rtl::OUString & rClashingName,
390 /* [out] */ uno::Any & rException,
391 /* [out] */ rtl::OUString & rNewName )
392 {
393 rtl::Reference< ucbhelper::SimpleNameClashResolveRequest > xRequest(
394 new ucbhelper::SimpleNameClashResolveRequest(
395 rTargetURL, // target folder URL
396 rClashingName, // clashing name
397 rtl::OUString(), // no proposal for new name
398 sal_True /* bSupportsOverwriteData */ ) );
399
400 rException = xRequest->getRequest();
401 if ( xEnv.is() )
402 {
403 uno::Reference< task::XInteractionHandler > xIH
404 = xEnv->getInteractionHandler();
405 if ( xIH.is() )
406 {
407
408 xIH->handle( xRequest.get() );
409
410 rtl::Reference< ucbhelper::InteractionContinuation >
411 xSelection( xRequest->getSelection() );
412
413 if ( xSelection.is() )
414 {
415 // Handler handled the request.
416 uno::Reference< task::XInteractionAbort > xAbort(
417 xSelection.get(), uno::UNO_QUERY );
418 if ( xAbort.is() )
419 {
420 // Abort.
421 return ABORT;
422 }
423 else
424 {
425 uno::Reference<
426 ucb::XInteractionReplaceExistingData >
427 xReplace(
428 xSelection.get(), uno::UNO_QUERY );
429 if ( xReplace.is() )
430 {
431 // Try again: Replace existing data.
432 return OVERWRITE;
433 }
434 else
435 {
436 uno::Reference<
437 ucb::XInteractionSupplyName >
438 xSupplyName(
439 xSelection.get(), uno::UNO_QUERY );
440 if ( xSupplyName.is() )
441 {
442 // Try again: Use new name.
443 rNewName = xRequest->getNewName();
444 return NEW_NAME;
445 }
446 else
447 {
448 OSL_ENSURE( sal_False,
449 "Unknown interaction continuation!" );
450 return UNKNOWN;
451 }
452 }
453 }
454 }
455 }
456 }
457 return NOT_HANDLED;
458 }
459
460 //=========================================================================
setTitle(const uno::Reference<ucb::XCommandProcessor> & xCommandProcessor,const uno::Reference<ucb::XCommandEnvironment> & xEnv,const rtl::OUString & rNewTitle)461 bool setTitle(
462 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessor,
463 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
464 const rtl::OUString & rNewTitle )
465 {
466 try
467 {
468 uno::Sequence< beans::PropertyValue > aPropValues( 1 );
469 aPropValues[ 0 ].Name
470 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) );
471 aPropValues[ 0 ].Handle = -1;
472 aPropValues[ 0 ].Value = uno::makeAny( rNewTitle );
473
474 ucb::Command aSetPropsCommand(
475 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
476 -1,
477 uno::makeAny( aPropValues ) );
478
479 uno::Any aResult
480 = xCommandProcessor->execute( aSetPropsCommand, 0, xEnv );
481
482 uno::Sequence< uno::Any > aErrors;
483 aResult >>= aErrors;
484
485 OSL_ENSURE( aErrors.getLength() == 1,
486 "getPropertyValues return value invalid!" );
487
488 if ( aErrors[ 0 ].hasValue() )
489 {
490 // error occurred.
491 OSL_ENSURE( sal_False, "error setting Title property!" );
492 return false;
493 }
494 }
495 catch ( uno::RuntimeException const & )
496 {
497 throw;
498 }
499 catch ( uno::Exception const & )
500 {
501 return false;
502 }
503
504 return true;
505 }
506
507 //=========================================================================
createNew(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xTarget,sal_Bool bSourceIsFolder,sal_Bool bSourceIsDocument,sal_Bool bSourceIsLink)508 uno::Reference< ucb::XContent > createNew(
509 const TransferCommandContext & rContext,
510 const uno::Reference< ucb::XContent > & xTarget,
511 sal_Bool bSourceIsFolder,
512 sal_Bool bSourceIsDocument,
513 sal_Bool bSourceIsLink )
514 {
515 //////////////////////////////////////////////////////////////////////
516 //
517 // (1) Obtain creatable types from target.
518 //
519 //////////////////////////////////////////////////////////////////////
520
521 // First, try it using "CreatabeleContentsInfo" property and
522 // "createNewContent" command -> the "new" way.
523
524 uno::Reference< ucb::XCommandProcessor > xCommandProcessorT(
525 xTarget, uno::UNO_QUERY );
526 if ( !xCommandProcessorT.is() )
527 {
528 uno::Any aProps
529 = uno::makeAny(beans::PropertyValue(
530 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
531 "Folder")),
532 -1,
533 uno::makeAny(rContext.aArg.TargetURL),
534 beans::PropertyState_DIRECT_VALUE));
535 ucbhelper::cancelCommandExecution(
536 ucb::IOErrorCode_CANT_CREATE,
537 uno::Sequence< uno::Any >(&aProps, 1),
538 rContext.xOrigEnv,
539 rtl::OUString::createFromAscii( "Target is no XCommandProcessor!" ),
540 rContext.xProcessor );
541 // Unreachable
542 }
543
544 uno::Sequence< beans::Property > aPropsToObtain( 1 );
545 aPropsToObtain[ 0 ].Name
546 = rtl::OUString::createFromAscii( "CreatableContentsInfo" );
547 aPropsToObtain[ 0 ].Handle
548 = -1;
549
550 ucb::Command aGetPropsCommand(
551 rtl::OUString::createFromAscii( "getPropertyValues" ),
552 -1,
553 uno::makeAny( aPropsToObtain ) );
554
555 uno::Reference< sdbc::XRow > xRow;
556 xCommandProcessorT->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
557
558 uno::Sequence< ucb::ContentInfo > aTypesInfo;
559 bool bGotTypesInfo = false;
560
561 if ( xRow.is() )
562 {
563 uno::Any aValue = xRow->getObject(
564 1, uno::Reference< container::XNameAccess >() );
565 if ( aValue.hasValue() && ( aValue >>= aTypesInfo ) )
566 {
567 bGotTypesInfo = true;
568 }
569 }
570
571 uno::Reference< ucb::XContentCreator > xCreator;
572
573 if ( !bGotTypesInfo )
574 {
575 // Second, try it using XContentCreator interface -> the "old" way (not
576 // providing the chance to supply an XCommandEnvironment.
577
578 xCreator.set( xTarget, uno::UNO_QUERY );
579
580 if ( !xCreator.is() )
581 {
582 uno::Any aProps
583 = uno::makeAny(beans::PropertyValue(
584 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
585 "Folder")),
586 -1,
587 uno::makeAny(rContext.aArg.TargetURL),
588 beans::PropertyState_DIRECT_VALUE));
589 ucbhelper::cancelCommandExecution(
590 ucb::IOErrorCode_CANT_CREATE,
591 uno::Sequence< uno::Any >(&aProps, 1),
592 rContext.xOrigEnv,
593 rtl::OUString::createFromAscii( "Target is no XContentCreator!" ),
594 rContext.xProcessor );
595 // Unreachable
596 }
597
598 aTypesInfo = xCreator->queryCreatableContentsInfo();
599 }
600
601 sal_Int32 nCount = aTypesInfo.getLength();
602 if ( !nCount )
603 {
604 uno::Any aProps
605 = uno::makeAny(beans::PropertyValue(
606 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Folder")),
607 -1,
608 uno::makeAny(rContext.aArg.TargetURL),
609 beans::PropertyState_DIRECT_VALUE));
610 ucbhelper::cancelCommandExecution(
611 ucb::IOErrorCode_CANT_CREATE,
612 uno::Sequence< uno::Any >(&aProps, 1),
613 rContext.xOrigEnv,
614 rtl::OUString::createFromAscii( "No types creatable!" ),
615 rContext.xProcessor );
616 // Unreachable
617 }
618
619 //////////////////////////////////////////////////////////////////////
620 //
621 // (2) Try to find a matching target type for the source object.
622 //
623 //////////////////////////////////////////////////////////////////////
624
625 uno::Reference< ucb::XContent > xNew;
626 for ( sal_Int32 n = 0; n < nCount; ++n )
627 {
628 sal_Int32 nAttribs = aTypesInfo[ n ].Attributes;
629 sal_Bool bMatch = sal_False;
630
631 if ( rContext.aArg.Operation == ucb::TransferCommandOperation_LINK )
632 {
633 // Create link
634
635 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
636 {
637 // Match!
638 bMatch = sal_True;
639 }
640 }
641 else if ( ( rContext.aArg.Operation
642 == ucb::TransferCommandOperation_COPY ) ||
643 ( rContext.aArg.Operation
644 == ucb::TransferCommandOperation_MOVE ) )
645 {
646 // Copy / Move
647
648 // Is source a link? Create link in target folder then.
649 if ( bSourceIsLink )
650 {
651 if ( nAttribs & ucb::ContentInfoAttribute::KIND_LINK )
652 {
653 // Match!
654 bMatch = sal_True;
655 }
656 }
657 else
658 {
659 // (not a and not b) or (a and b)
660 // not( a or b) or (a and b)
661 //
662 if ( ( !!bSourceIsFolder ==
663 !!( nAttribs
664 & ucb::ContentInfoAttribute::KIND_FOLDER ) )
665 &&
666 ( !!bSourceIsDocument ==
667 !!( nAttribs
668 & ucb::ContentInfoAttribute::KIND_DOCUMENT ) )
669 )
670 {
671 // Match!
672 bMatch = sal_True;
673 }
674 }
675 }
676 else
677 {
678 ucbhelper::cancelCommandExecution(
679 uno::makeAny( lang::IllegalArgumentException(
680 rtl::OUString::createFromAscii(
681 "Unknown transfer operation!" ),
682 rContext.xProcessor,
683 -1 ) ),
684 rContext.xOrigEnv );
685 // Unreachable
686 }
687
688 if ( bMatch )
689 {
690 //////////////////////////////////////////////////////////////
691 //
692 // (3) Create a new, empty object of matched type.
693 //
694 //////////////////////////////////////////////////////////////
695
696 if ( !xCreator.is() )
697 {
698 // First, try it using "CreatabeleContentsInfo" property and
699 // "createNewContent" command -> the "new" way.
700 ucb::Command aCreateNewCommand(
701 rtl::OUString::createFromAscii( "createNewContent" ),
702 -1,
703 uno::makeAny( aTypesInfo[ n ] ) );
704
705 xCommandProcessorT->execute( aCreateNewCommand, 0, rContext.xEnv )
706 >>= xNew;
707 }
708 else
709 {
710 // Second, try it using XContentCreator interface -> the "old"
711 // way (not providing the chance to supply an XCommandEnvironment.
712
713 xNew = xCreator->createNewContent( aTypesInfo[ n ] );
714 }
715
716 if ( !xNew.is() )
717 {
718 uno::Any aProps
719 = uno::makeAny(
720 beans::PropertyValue(
721 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
722 "Folder")),
723 -1,
724 uno::makeAny(rContext.aArg.TargetURL),
725 beans::PropertyState_DIRECT_VALUE));
726 ucbhelper::cancelCommandExecution(
727 ucb::IOErrorCode_CANT_CREATE,
728 uno::Sequence< uno::Any >(&aProps, 1),
729 rContext.xOrigEnv,
730 rtl::OUString::createFromAscii(
731 "createNewContent failed!" ),
732 rContext.xProcessor );
733 // Unreachable
734 }
735 break; // escape from 'for' loop
736 }
737 } // for
738
739 return xNew;
740 }
741
742 //=========================================================================
transferProperties(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorN)743 void transferProperties(
744 const TransferCommandContext & rContext,
745 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS,
746 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorN )
747 {
748 ucb::Command aGetPropertySetInfoCommand(
749 rtl::OUString::createFromAscii( "getPropertySetInfo" ),
750 -1,
751 uno::Any() );
752
753 uno::Reference< beans::XPropertySetInfo > xInfo;
754 xCommandProcessorS->execute( aGetPropertySetInfoCommand, 0, rContext.xEnv )
755 >>= xInfo;
756
757 if ( !xInfo.is() )
758 {
759 uno::Any aProps
760 = uno::makeAny(beans::PropertyValue(
761 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
762 "Uri")),
763 -1,
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),
769 rContext.xOrigEnv,
770 rtl::OUString::createFromAscii(
771 "Unable to get propertyset info from source object!" ),
772 rContext.xProcessor );
773 // Unreachable
774 }
775
776 uno::Sequence< beans::Property > aAllProps = xInfo->getProperties();
777
778 ucb::Command aGetPropsCommand1(
779 rtl::OUString::createFromAscii( "getPropertyValues" ),
780 -1,
781 uno::makeAny( aAllProps ) );
782
783 uno::Reference< sdbc::XRow > xRow1;
784 xCommandProcessorS->execute(
785 aGetPropsCommand1, 0, rContext.xEnv ) >>= xRow1;
786
787 if ( !xRow1.is() )
788 {
789 uno::Any aProps
790 = uno::makeAny(beans::PropertyValue(
791 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
792 "Uri")),
793 -1,
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),
799 rContext.xOrigEnv,
800 rtl::OUString::createFromAscii(
801 "Unable to get properties from source object!" ),
802 rContext.xProcessor );
803 // Unreachable
804 }
805
806 // Assemble data structure for setPropertyValues command.
807
808 // Note: Make room for additional Title and TargetURL too. -> + 2
809 uno::Sequence< beans::PropertyValue > aPropValues(
810 aAllProps.getLength() + 2 );
811
812 sal_Bool bHasTitle = ( rContext.aArg.NewTitle.getLength() == 0 );
813 sal_Bool bHasTargetURL = ( rContext.aArg.Operation
814 != ucb::TransferCommandOperation_LINK );
815
816 sal_Int32 nWritePos = 0;
817 for ( sal_Int32 m = 0; m < aAllProps.getLength(); ++m )
818 {
819 const beans::Property & rCurrProp = aAllProps[ m ];
820 beans::PropertyValue & rCurrValue = aPropValues[ nWritePos ];
821
822 uno::Any aValue;
823
824 if ( rCurrProp.Name.compareToAscii( "Title" ) == 0 )
825 {
826 // Supply new title, if given.
827 if ( !bHasTitle )
828 {
829 bHasTitle = sal_True;
830 aValue <<= rContext.aArg.NewTitle;
831 }
832 }
833 else if ( rCurrProp.Name.compareToAscii( "TargetURL" ) == 0 )
834 {
835 // Supply source URL as link target for the new link to create.
836 if ( !bHasTargetURL )
837 {
838 bHasTargetURL = sal_True;
839 aValue <<= rContext.aArg.SourceURL;
840 }
841 }
842
843 if ( !aValue.hasValue() )
844 {
845 try
846 {
847 aValue = xRow1->getObject(
848 m + 1, uno::Reference< container::XNameAccess >() );
849 }
850 catch ( sdbc::SQLException const & )
851 {
852 // Argh! But try to bring things to an end. Perhaps the
853 // mad property is not really important...
854 }
855 }
856
857 if ( aValue.hasValue() )
858 {
859 rCurrValue.Name = rCurrProp.Name;
860 rCurrValue.Handle = rCurrProp.Handle;
861 rCurrValue.Value = aValue;
862 // rCurrValue.State =
863
864 nWritePos++;
865 }
866 }
867
868 // Title needed, but not set yet?
869 if ( !bHasTitle && ( rContext.aArg.NewTitle.getLength() > 0 ) )
870 {
871 aPropValues[ nWritePos ].Name
872 = rtl::OUString::createFromAscii( "Title" );
873 aPropValues[ nWritePos ].Handle = -1;
874 aPropValues[ nWritePos ].Value <<= rContext.aArg.NewTitle;
875
876 nWritePos++;
877 }
878
879 // TargetURL needed, but not set yet?
880 if ( !bHasTargetURL && ( rContext.aArg.Operation
881 == ucb::TransferCommandOperation_LINK ) )
882 {
883 aPropValues[ nWritePos ].Name
884 = rtl::OUString::createFromAscii( "TargetURL" );
885 aPropValues[ nWritePos ].Handle = -1;
886 aPropValues[ nWritePos ].Value <<= rContext.aArg.SourceURL;
887
888 nWritePos++;
889 }
890
891 aPropValues.realloc( nWritePos );
892
893 // Set properties at new object.
894
895 ucb::Command aSetPropsCommand(
896 rtl::OUString::createFromAscii( "setPropertyValues" ),
897 -1,
898 uno::makeAny( aPropValues ) );
899
900 xCommandProcessorN->execute( aSetPropsCommand, 0, rContext.xEnv );
901
902 // @@@ What to do with source props that are not supported by the
903 // new object? addProperty ???
904 }
905
906 //=========================================================================
getInputStream(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS)907 uno::Reference< io::XInputStream > getInputStream(
908 const TransferCommandContext & rContext,
909 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
910 {
911 uno::Reference< io::XInputStream > xInputStream;
912
913 //////////////////////////////////////////////////////////////////////
914 //
915 // (1) Try to get data as XInputStream via XActiveDataSink.
916 //
917 //////////////////////////////////////////////////////////////////////
918
919 try
920 {
921 uno::Reference< io::XActiveDataSink > xSink = new ActiveDataSink;
922
923 ucb::OpenCommandArgument2 aArg;
924 aArg.Mode = ucb::OpenMode::DOCUMENT;
925 aArg.Priority = 0; // unused
926 aArg.Sink = xSink;
927 aArg.Properties = uno::Sequence< beans::Property >( 0 ); // unused
928
929 ucb::Command aOpenCommand(
930 rtl::OUString::createFromAscii( "open" ),
931 -1,
932 uno::makeAny( aArg ) );
933
934 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
935 xInputStream = xSink->getInputStream();
936 }
937 catch ( uno::RuntimeException const & )
938 {
939 throw;
940 }
941 catch ( uno::Exception const & )
942 {
943 // will be handled below.
944 }
945
946 if ( !xInputStream.is() )
947 {
948 //////////////////////////////////////////////////////////////////
949 //
950 // (2) Try to get data via XOutputStream.
951 //
952 //////////////////////////////////////////////////////////////////
953
954 try
955 {
956 uno::Reference< io::XOutputStream > xOutputStream(
957 rContext.xSMgr->createInstance(
958 rtl::OUString::createFromAscii( "com.sun.star.io.Pipe" ) ),
959 uno::UNO_QUERY );
960
961 if ( xOutputStream.is() )
962 {
963 ucb::OpenCommandArgument2 aArg;
964 aArg.Mode = ucb::OpenMode::DOCUMENT;
965 aArg.Priority = 0; // unused
966 aArg.Sink = xOutputStream;
967 aArg.Properties = uno::Sequence< beans::Property >( 0 );
968
969 ucb::Command aOpenCommand(
970 rtl::OUString::createFromAscii( "open" ),
971 -1,
972 uno::makeAny( aArg ) );
973
974 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv );
975
976 xInputStream = uno::Reference< io::XInputStream >(
977 xOutputStream, uno::UNO_QUERY );
978 }
979 }
980 catch ( uno::RuntimeException const & )
981 {
982 throw;
983 }
984 catch ( uno::Exception const & )
985 {
986 OSL_ENSURE( sal_False, "unable to get input stream from document!" );
987 }
988 }
989
990 return xInputStream;
991 }
992
993 //=========================================================================
getResultSet(const TransferCommandContext & rContext,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS)994 uno::Reference< sdbc::XResultSet > getResultSet(
995 const TransferCommandContext & rContext,
996 const uno::Reference< ucb::XCommandProcessor > & xCommandProcessorS )
997 {
998 uno::Reference< sdbc::XResultSet > xResultSet;
999
1000 uno::Sequence< beans::Property > aProps( 3 );
1001
1002 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
1003 aProps[ 0 ].Handle = -1; /* unknown */
1004 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
1005 aProps[ 1 ].Handle = -1; /* unknown */
1006 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
1007 aProps[ 2 ].Handle = -1; /* unknown */
1008
1009 ucb::OpenCommandArgument2 aArg;
1010 aArg.Mode = ucb::OpenMode::ALL;
1011 aArg.Priority = 0; // unused
1012 aArg.Sink = 0;
1013 aArg.Properties = aProps;
1014
1015 ucb::Command aOpenCommand( rtl::OUString::createFromAscii( "open" ),
1016 -1,
1017 uno::makeAny( aArg ) );
1018 try
1019 {
1020 uno::Reference< ucb::XDynamicResultSet > xSet;
1021 xCommandProcessorS->execute( aOpenCommand, 0, rContext.xEnv ) >>= xSet;
1022
1023 if ( xSet.is() )
1024 xResultSet = xSet->getStaticResultSet();
1025 }
1026 catch ( uno::RuntimeException const & )
1027 {
1028 throw;
1029 }
1030 catch ( uno::Exception const & )
1031 {
1032 OSL_ENSURE( sal_False, "unable to get result set from folder!" );
1033 }
1034
1035 return xResultSet;
1036 }
1037
1038 //=========================================================================
handleNameClashRename(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xNew,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorN,const uno::Reference<ucb::XCommandProcessor> & xCommandProcessorS,uno::Reference<io::XInputStream> & xInputStream)1039 void handleNameClashRename(
1040 const TransferCommandContext & rContext,
1041 const uno::Reference< ucb::XContent > & xNew,
1042 const uno::Reference<
1043 ucb::XCommandProcessor > & xCommandProcessorN,
1044 const uno::Reference<
1045 ucb::XCommandProcessor > & xCommandProcessorS,
1046 /* [inout] */ uno::Reference< io::XInputStream > & xInputStream )
1047 {
1048 sal_Int32 nTry = 0;
1049
1050 // Obtain old title.
1051 uno::Sequence< beans::Property > aProps( 1 );
1052 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "Title" );
1053 aProps[ 0 ].Handle = -1;
1054
1055 ucb::Command aGetPropsCommand(
1056 rtl::OUString::createFromAscii( "getPropertyValues" ),
1057 -1,
1058 uno::makeAny( aProps ) );
1059
1060 uno::Reference< sdbc::XRow > xRow;
1061 xCommandProcessorN->execute( aGetPropsCommand, 0, rContext.xEnv ) >>= xRow;
1062
1063 if ( !xRow.is() )
1064 {
1065 uno::Any aProps2
1066 = uno::makeAny(
1067 beans::PropertyValue(
1068 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1069 -1,
1070 uno::makeAny(
1071 xNew->getIdentifier()->getContentIdentifier() ),
1072 beans::PropertyState_DIRECT_VALUE ) );
1073 ucbhelper::cancelCommandExecution(
1074 ucb::IOErrorCode_CANT_READ,
1075 uno::Sequence< uno::Any >( &aProps2, 1 ),
1076 rContext.xOrigEnv,
1077 rtl::OUString::createFromAscii(
1078 "Unable to get properties from new object!" ),
1079 rContext.xProcessor );
1080 // Unreachable
1081 }
1082
1083 rtl::OUString aOldTitle = xRow->getString( 1 );
1084 if ( !aOldTitle.getLength() )
1085 {
1086 ucbhelper::cancelCommandExecution(
1087 uno::makeAny( beans::UnknownPropertyException(
1088 rtl::OUString::createFromAscii(
1089 "Unable to get property 'Title' "
1090 "from new object!" ),
1091 rContext.xProcessor ) ),
1092 rContext.xOrigEnv );
1093 // Unreachable
1094 }
1095
1096 // Some pseudo-intelligence for not destroying file extensions.
1097 rtl::OUString aOldTitlePre;
1098 rtl::OUString aOldTitlePost;
1099 sal_Int32 nPos = aOldTitle.lastIndexOf( '.' );
1100 if ( nPos != -1 )
1101 {
1102 aOldTitlePre = aOldTitle.copy( 0, nPos );
1103 aOldTitlePost = aOldTitle.copy( nPos );
1104 }
1105 else
1106 aOldTitlePre = aOldTitle;
1107
1108 if ( nPos > 0 )
1109 aOldTitlePre += rtl::OUString::createFromAscii( "_" );
1110
1111 sal_Bool bContinue = sal_True;
1112 do
1113 {
1114 nTry++;
1115
1116 rtl::OUString aNewTitle = aOldTitlePre;
1117 aNewTitle += rtl::OUString::valueOf( nTry );
1118 aNewTitle += aOldTitlePost;
1119
1120 // Set new title
1121 setTitle( xCommandProcessorN, rContext.xEnv, aNewTitle );
1122
1123 // Retry inserting the content.
1124 try
1125 {
1126 // Previous try may have read from stream. Seek to begin (if
1127 // optional interface XSeekable is supported) or get a new stream.
1128 if ( xInputStream.is() )
1129 {
1130 uno::Reference< io::XSeekable > xSeekable(
1131 xInputStream, uno::UNO_QUERY );
1132 if ( xSeekable.is() )
1133 {
1134 try
1135 {
1136 xSeekable->seek( 0 );
1137 }
1138 catch ( lang::IllegalArgumentException const & )
1139 {
1140 xInputStream.clear();
1141 }
1142 catch ( io::IOException const & )
1143 {
1144 xInputStream.clear();
1145 }
1146 }
1147 else
1148 xInputStream.clear();
1149
1150 if ( !xInputStream.is() )
1151 {
1152 xInputStream
1153 = getInputStream( rContext, xCommandProcessorS );
1154 if ( !xInputStream.is() )
1155 {
1156 uno::Any aProps2
1157 = uno::makeAny(
1158 beans::PropertyValue(
1159 rtl::OUString(
1160 RTL_CONSTASCII_USTRINGPARAM( "Uri" ) ),
1161 -1,
1162 uno::makeAny(
1163 xNew->getIdentifier()->
1164 getContentIdentifier() ),
1165 beans::PropertyState_DIRECT_VALUE ) );
1166 ucbhelper::cancelCommandExecution(
1167 ucb::IOErrorCode_CANT_READ,
1168 uno::Sequence< uno::Any >( &aProps2, 1 ),
1169 rContext.xOrigEnv,
1170 rtl::OUString::createFromAscii(
1171 "Got no data stream from source!" ),
1172 rContext.xProcessor );
1173 // Unreachable
1174 }
1175 }
1176 }
1177
1178 ucb::InsertCommandArgument aArg;
1179 aArg.Data = xInputStream;
1180 aArg.ReplaceExisting = sal_False;
1181
1182 ucb::Command aInsertCommand(
1183 rtl::OUString::createFromAscii( "insert" ),
1184 -1,
1185 uno::makeAny( aArg ) );
1186
1187 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1188
1189 // Success!
1190 bContinue = sal_False;
1191 }
1192 catch ( uno::RuntimeException const & )
1193 {
1194 throw;
1195 }
1196 catch ( uno::Exception const & )
1197 {
1198 }
1199 }
1200 while ( bContinue && ( nTry < 50 ) );
1201
1202 if ( nTry == 50 )
1203 {
1204 ucbhelper::cancelCommandExecution(
1205 uno::makeAny(
1206 ucb::UnsupportedNameClashException(
1207 rtl::OUString::createFromAscii(
1208 "Unable to resolve name clash!" ),
1209 rContext.xProcessor,
1210 ucb::NameClash::RENAME ) ),
1211 rContext.xOrigEnv );
1212 // Unreachable
1213 }
1214 }
1215
1216 //=========================================================================
globalTransfer_(const TransferCommandContext & rContext,const uno::Reference<ucb::XContent> & xSource,const uno::Reference<ucb::XContent> & xTarget,const uno::Reference<sdbc::XRow> & xSourceProps)1217 void globalTransfer_(
1218 const TransferCommandContext & rContext,
1219 const uno::Reference< ucb::XContent > & xSource,
1220 const uno::Reference< ucb::XContent > & xTarget,
1221 const uno::Reference< sdbc::XRow > & xSourceProps )
1222 {
1223 // IsFolder: property is required.
1224 sal_Bool bSourceIsFolder = xSourceProps->getBoolean( 1 );
1225 if ( !bSourceIsFolder && xSourceProps->wasNull() )
1226 {
1227 ucbhelper::cancelCommandExecution(
1228 uno::makeAny( beans::UnknownPropertyException(
1229 rtl::OUString::createFromAscii(
1230 "Unable to get property 'IsFolder' "
1231 "from source object!" ),
1232 rContext.xProcessor ) ),
1233 rContext.xOrigEnv );
1234 // Unreachable
1235 }
1236
1237 // IsDocument: property is required.
1238 sal_Bool bSourceIsDocument = xSourceProps->getBoolean( 2 );
1239 if ( !bSourceIsDocument && xSourceProps->wasNull() )
1240 {
1241 ucbhelper::cancelCommandExecution(
1242 uno::makeAny( beans::UnknownPropertyException(
1243 rtl::OUString::createFromAscii(
1244 "Unable to get property 'IsDocument' "
1245 "from source object!" ),
1246 rContext.xProcessor ) ),
1247 rContext.xOrigEnv );
1248 // Unreachable
1249 }
1250
1251 // TargetURL: property is optional.
1252 sal_Bool bSourceIsLink = ( xSourceProps->getString( 3 ).getLength() > 0 );
1253
1254 //////////////////////////////////////////////////////////////////////
1255 //
1256 // (1) Try to find a matching target type for the source object and
1257 // create a new, empty object of that type.
1258 //
1259 //////////////////////////////////////////////////////////////////////
1260
1261 uno::Reference< ucb::XContent > xNew = createNew( rContext,
1262 xTarget,
1263 bSourceIsFolder,
1264 bSourceIsDocument,
1265 bSourceIsLink );
1266 if ( !xNew.is() )
1267 {
1268 uno::Any aProps
1269 = uno::makeAny(beans::PropertyValue(
1270 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1271 "Folder")),
1272 -1,
1273 uno::makeAny(rContext.aArg.TargetURL),
1274 beans::PropertyState_DIRECT_VALUE));
1275 ucbhelper::cancelCommandExecution(
1276 ucb::IOErrorCode_CANT_CREATE,
1277 uno::Sequence< uno::Any >(&aProps, 1),
1278 rContext.xOrigEnv,
1279 rtl::OUString::createFromAscii(
1280 "No matching content type at target!" ),
1281 rContext.xProcessor );
1282 // Unreachable
1283 }
1284
1285 //////////////////////////////////////////////////////////////////////
1286 //
1287 // (2) Transfer property values from source to new object.
1288 //
1289 //////////////////////////////////////////////////////////////////////
1290
1291 uno::Reference< ucb::XCommandProcessor > xCommandProcessorN(
1292 xNew, uno::UNO_QUERY );
1293 if ( !xCommandProcessorN.is() )
1294 {
1295 uno::Any aProps
1296 = uno::makeAny(beans::PropertyValue(
1297 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1298 "Uri")),
1299 -1,
1300 uno::makeAny(
1301 xNew->getIdentifier()->
1302 getContentIdentifier()),
1303 beans::PropertyState_DIRECT_VALUE));
1304 ucbhelper::cancelCommandExecution(
1305 ucb::IOErrorCode_CANT_WRITE,
1306 uno::Sequence< uno::Any >(&aProps, 1),
1307 rContext.xOrigEnv,
1308 rtl::OUString::createFromAscii(
1309 "New content is not a XCommandProcessor!" ),
1310 rContext.xProcessor );
1311 // Unreachable
1312 }
1313
1314 // Obtain all properties from source.
1315
1316 uno::Reference< ucb::XCommandProcessor > xCommandProcessorS(
1317 xSource, uno::UNO_QUERY );
1318 if ( !xCommandProcessorS.is() )
1319 {
1320 uno::Any aProps
1321 = uno::makeAny(beans::PropertyValue(
1322 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1323 "Uri")),
1324 -1,
1325 uno::makeAny(rContext.aArg.SourceURL),
1326 beans::PropertyState_DIRECT_VALUE));
1327 ucbhelper::cancelCommandExecution(
1328 ucb::IOErrorCode_CANT_READ,
1329 uno::Sequence< uno::Any >(&aProps, 1),
1330 rContext.xOrigEnv,
1331 rtl::OUString::createFromAscii(
1332 "Source content is not a XCommandProcessor!" ),
1333 rContext.xProcessor );
1334 // Unreachable
1335 }
1336
1337 transferProperties( rContext, xCommandProcessorS, xCommandProcessorN );
1338
1339 //////////////////////////////////////////////////////////////////////
1340 //
1341 // (3) Try to obtain a data stream from source.
1342 //
1343 //////////////////////////////////////////////////////////////////////
1344
1345 uno::Reference< io::XInputStream > xInputStream;
1346
1347 if ( bSourceIsDocument && ( rContext.aArg.Operation
1348 != ucb::TransferCommandOperation_LINK ) )
1349 xInputStream = getInputStream( rContext, xCommandProcessorS );
1350
1351 //////////////////////////////////////////////////////////////////////
1352 //
1353 // (4) Try to obtain a resultset (children) from source.
1354 //
1355 //////////////////////////////////////////////////////////////////////
1356
1357 uno::Reference< sdbc::XResultSet > xResultSet;
1358
1359 if ( bSourceIsFolder && ( rContext.aArg.Operation
1360 != ucb::TransferCommandOperation_LINK ) )
1361 xResultSet = getResultSet( rContext, xCommandProcessorS );
1362
1363 //////////////////////////////////////////////////////////////////////
1364 //
1365 // (5) Insert (store) new content.
1366 //
1367 //////////////////////////////////////////////////////////////////////
1368
1369 ucb::InsertCommandArgument aArg;
1370 aArg.Data = xInputStream;
1371
1372 switch ( rContext.aArg.NameClash )
1373 {
1374 case ucb::NameClash::OVERWRITE:
1375 aArg.ReplaceExisting = sal_True;
1376 break;
1377
1378 case ucb::NameClash::ERROR:
1379 case ucb::NameClash::RENAME:
1380 case ucb::NameClash::KEEP: // deprecated
1381 case ucb::NameClash::ASK:
1382 aArg.ReplaceExisting = sal_False;
1383 break;
1384
1385 default:
1386 aArg.ReplaceExisting = sal_False;
1387 OSL_ENSURE( sal_False, "Unknown nameclash directive!" );
1388 break;
1389 }
1390
1391 rtl::OUString aDesiredName = createDesiredName( rContext.aArg );
1392
1393 bool bRetry;
1394 do
1395 {
1396 bRetry = false;
1397
1398 try
1399 {
1400 ucb::Command aInsertCommand(
1401 rtl::OUString::createFromAscii( "insert" ),
1402 -1,
1403 uno::makeAny( aArg ) );
1404
1405 xCommandProcessorN->execute( aInsertCommand, 0, rContext.xEnv );
1406 }
1407 catch ( ucb::UnsupportedNameClashException const & exc )
1408 {
1409 OSL_ENSURE( !aArg.ReplaceExisting,
1410 "BUG: UnsupportedNameClashException not allowed here!" );
1411
1412 if (exc.NameClash != ucb::NameClash::ERROR) {
1413 OSL_ENSURE( false, "BUG: NameClash::ERROR expected!" );
1414 }
1415
1416 // No chance to solve name clashes, because I'm not able to detect
1417 // whether there is one.
1418 throw ucb::UnsupportedNameClashException(
1419 rtl::OUString::createFromAscii(
1420 "Unable to resolve name clashes, no chance to detect "
1421 "that there is one!" ),
1422 rContext.xProcessor,
1423 rContext.aArg.NameClash );
1424 }
1425 catch ( ucb::NameClashException const & )
1426 {
1427 // The 'insert' command throws a NameClashException if the parameter
1428 // ReplaceExisting of the command's argument was set to false and
1429 // there exists a resource with a clashing name in the target folder
1430 // of the operation.
1431
1432 // 'insert' command has no direct support for name clashes other
1433 // than ERROR ( ReplaceExisting == false ) and OVERWRITE
1434 // ( ReplaceExisting == true ). So we have to implement the
1435 // other name clash handling directives on top of the content.
1436
1437 // @@@ 'insert' command should be extended that it accepts a
1438 // name clash handling directive, exactly like 'transfer' command.
1439
1440 switch ( rContext.aArg.NameClash )
1441 {
1442 case ucb::NameClash::OVERWRITE:
1443 {
1444 ucbhelper::cancelCommandExecution(
1445 uno::makeAny(
1446 ucb::UnsupportedNameClashException(
1447 rtl::OUString::createFromAscii(
1448 "BUG: insert + replace == true MUST NOT "
1449 "throw NameClashException." ),
1450 rContext.xProcessor,
1451 rContext.aArg.NameClash ) ),
1452 rContext.xOrigEnv );
1453 // Unreachable
1454 }
1455
1456 case ucb::NameClash::ERROR:
1457 throw;
1458
1459 case ucb::NameClash::RENAME:
1460 {
1461 // "invent" a new valid title.
1462 handleNameClashRename( rContext,
1463 xNew,
1464 xCommandProcessorN,
1465 xCommandProcessorS,
1466 xInputStream );
1467 break;
1468 }
1469
1470 case ucb::NameClash::ASK:
1471 {
1472 uno::Any aExc;
1473 rtl::OUString aNewTitle;
1474 NameClashContinuation eCont
1475 = interactiveNameClashResolve(
1476 rContext.xOrigEnv, // always use original environment!
1477 rContext.aArg.TargetURL, // target folder URL
1478 aDesiredName,
1479 aExc,
1480 aNewTitle );
1481
1482 switch ( eCont )
1483 {
1484 case NOT_HANDLED:
1485 // Not handled.
1486 cppu::throwException( aExc );
1487 // break;
1488
1489 case UNKNOWN:
1490 // Handled, but not clear, how...
1491 // fall-thru intended.
1492
1493 case ABORT:
1494 throw ucb::CommandFailedException(
1495 rtl::OUString(
1496 RTL_CONSTASCII_USTRINGPARAM(
1497 "abort requested via interaction "
1498 "handler" ) ),
1499 uno::Reference< uno::XInterface >(),
1500 aExc );
1501 // break;
1502
1503 case OVERWRITE:
1504 OSL_ENSURE( aArg.ReplaceExisting == sal_False,
1505 "Hu? ReplaceExisting already true?"
1506 );
1507 aArg.ReplaceExisting = sal_True;
1508 bRetry = true;
1509 break;
1510
1511 case NEW_NAME:
1512 {
1513 // set new name -> set "Title" property...
1514 if ( setTitle( xCommandProcessorN,
1515 rContext.xEnv,
1516 aNewTitle ) )
1517 {
1518 // remember suggested title...
1519 aDesiredName = aNewTitle;
1520
1521 // ... and try again.
1522 bRetry = true;
1523 }
1524 else
1525 {
1526 // error setting title. Abort.
1527 throw ucb::CommandFailedException(
1528 rtl::OUString(
1529 RTL_CONSTASCII_USTRINGPARAM(
1530 "error setting Title property!"
1531 ) ),
1532 uno::Reference< uno::XInterface >(),
1533 aExc );
1534 }
1535 break;
1536 }
1537 }
1538
1539 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1540 }
1541 break;
1542
1543 case ucb::NameClash::KEEP: // deprecated
1544 default:
1545 {
1546 ucbhelper::cancelCommandExecution(
1547 uno::makeAny(
1548 ucb::UnsupportedNameClashException(
1549 rtl::OUString(
1550 RTL_CONSTASCII_USTRINGPARAM(
1551 "default action, don't know how to "
1552 "handle name clash" ) ),
1553 rContext.xProcessor,
1554 rContext.aArg.NameClash ) ),
1555 rContext.xOrigEnv );
1556 // Unreachable
1557 }
1558 }
1559 }
1560 }
1561 while ( bRetry );
1562
1563 //////////////////////////////////////////////////////////////////////
1564 //
1565 // (6) Process children of source.
1566 //
1567 //////////////////////////////////////////////////////////////////////
1568
1569 if ( xResultSet.is() )
1570 {
1571 try
1572 {
1573 // Iterate over children...
1574
1575 uno::Reference< sdbc::XRow > xChildRow(
1576 xResultSet, uno::UNO_QUERY );
1577
1578 if ( !xChildRow.is() )
1579 {
1580 uno::Any aProps
1581 = uno::makeAny(
1582 beans::PropertyValue(
1583 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1584 "Uri")),
1585 -1,
1586 uno::makeAny(rContext.aArg.SourceURL),
1587 beans::PropertyState_DIRECT_VALUE));
1588 ucbhelper::cancelCommandExecution(
1589 ucb::IOErrorCode_CANT_READ,
1590 uno::Sequence< uno::Any >(&aProps, 1),
1591 rContext.xOrigEnv,
1592 rtl::OUString::createFromAscii(
1593 "Unable to get properties from children of source!" ),
1594 rContext.xProcessor );
1595 // Unreachable
1596 }
1597
1598 uno::Reference< ucb::XContentAccess > xChildAccess(
1599 xResultSet, uno::UNO_QUERY );
1600
1601 if ( !xChildAccess.is() )
1602 {
1603 uno::Any aProps
1604 = uno::makeAny(
1605 beans::PropertyValue(
1606 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1607 "Uri")),
1608 -1,
1609 uno::makeAny(rContext.aArg.SourceURL),
1610 beans::PropertyState_DIRECT_VALUE));
1611 ucbhelper::cancelCommandExecution(
1612 ucb::IOErrorCode_CANT_READ,
1613 uno::Sequence< uno::Any >(&aProps, 1),
1614 rContext.xOrigEnv,
1615 rtl::OUString::createFromAscii(
1616 "Unable to get children of source!" ),
1617 rContext.xProcessor );
1618 // Unreachable
1619 }
1620
1621 if ( xResultSet->first() )
1622 {
1623 ucb::GlobalTransferCommandArgument aTransArg(
1624 rContext.aArg.Operation, // Operation
1625 rtl::OUString(), // SourceURL; filled later
1626 xNew->getIdentifier()
1627 ->getContentIdentifier(), // TargetURL
1628 rtl::OUString(), // NewTitle;
1629 rContext.aArg.NameClash ); // NameClash
1630
1631 TransferCommandContext aSubCtx(
1632 rContext.xSMgr,
1633 rContext.xProcessor,
1634 rContext.xEnv,
1635 rContext.xOrigEnv,
1636 aTransArg );
1637 do
1638 {
1639 uno::Reference< ucb::XContent > xChild
1640 = xChildAccess->queryContent();
1641 if ( xChild.is() )
1642 {
1643 // Recursion!
1644
1645 aSubCtx.aArg.SourceURL
1646 = xChild->getIdentifier()->getContentIdentifier();
1647
1648 globalTransfer_( aSubCtx,
1649 xChild,
1650 xNew,
1651 xChildRow );
1652 }
1653 }
1654 while ( xResultSet->next() );
1655 }
1656 }
1657 catch ( sdbc::SQLException const & )
1658 {
1659 }
1660 }
1661
1662 try {
1663 uno::Reference< ucb::XCommandProcessor > xcp(
1664 xTarget, uno::UNO_QUERY );
1665
1666 uno::Any aAny;
1667 uno::Reference< ucb::XCommandInfo > xci;
1668 if(xcp.is())
1669 aAny =
1670 xcp->execute(
1671 ucb::Command(
1672 rtl::OUString::createFromAscii("getCommandInfo"),
1673 -1,
1674 uno::Any()),
1675 0,
1676 rContext.xEnv );
1677
1678 const rtl::OUString cmdName =
1679 rtl::OUString::createFromAscii("flush");
1680 if((aAny >>= xci) && xci->hasCommandByName(cmdName))
1681 xcp->execute(
1682 ucb::Command(
1683 cmdName,
1684 -1,
1685 uno::Any()) ,
1686 0,
1687 rContext.xEnv );
1688 }
1689 catch( uno::Exception const & )
1690 {
1691 }
1692 }
1693
1694 } /* namescpace */
1695
1696 //=========================================================================
1697 //
1698 // UniversalContentBroker implementation ( XCommandProcessor commands ).
1699 //
1700 //=========================================================================
1701
1702 uno::Reference< ucb::XCommandInfo >
getCommandInfo()1703 UniversalContentBroker::getCommandInfo()
1704 {
1705 return uno::Reference< ucb::XCommandInfo >( new CommandProcessorInfo() );
1706 }
1707
1708 //=========================================================================
globalTransfer(const ucb::GlobalTransferCommandArgument & rArg,const uno::Reference<ucb::XCommandEnvironment> & xEnv)1709 void UniversalContentBroker::globalTransfer(
1710 const ucb::GlobalTransferCommandArgument & rArg,
1711 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1712 {
1713 // Use own command environment with own interaction handler intercepting
1714 // some interaction requests that shall not be handled by the user-supplied
1715 // interaction handler.
1716 uno::Reference< ucb::XCommandEnvironment > xLocalEnv;
1717 if (xEnv.is())
1718 {
1719 uno::Reference< beans::XPropertySet > const xProps(
1720 m_xSMgr, uno::UNO_QUERY_THROW );
1721 uno::Reference< uno::XComponentContext > xCtx;
1722 xCtx.set( xProps->getPropertyValue(
1723 rtl::OUString(
1724 RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ),
1725 uno::UNO_QUERY_THROW );
1726
1727 xLocalEnv.set( ucb::CommandEnvironment::create(
1728 xCtx,
1729 new InteractionHandlerProxy( xEnv->getInteractionHandler() ),
1730 xEnv->getProgressHandler() ) );
1731 }
1732
1733 //////////////////////////////////////////////////////////////////////
1734 //
1735 // (1) Try to transfer the content using 'transfer' command.
1736 //
1737 //////////////////////////////////////////////////////////////////////
1738
1739 uno::Reference< ucb::XContent > xTarget;
1740 uno::Reference< ucb::XContentIdentifier > xId
1741 = createContentIdentifier( rArg.TargetURL );
1742 if ( xId.is() )
1743 {
1744 try
1745 {
1746 xTarget = queryContent( xId );
1747 }
1748 catch ( ucb::IllegalIdentifierException const & )
1749 {
1750 }
1751 }
1752
1753 if ( !xTarget.is() )
1754 {
1755 uno::Any aProps
1756 = uno::makeAny(beans::PropertyValue(
1757 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1758 "Uri")),
1759 -1,
1760 uno::makeAny(rArg.TargetURL),
1761 beans::PropertyState_DIRECT_VALUE));
1762 ucbhelper::cancelCommandExecution(
1763 ucb::IOErrorCode_CANT_READ,
1764 uno::Sequence< uno::Any >(&aProps, 1),
1765 xEnv,
1766 rtl::OUString::createFromAscii(
1767 "Can't instantiate target object!" ),
1768 this );
1769 // Unreachable
1770 }
1771
1772 if ( ( rArg.Operation == ucb::TransferCommandOperation_COPY ) ||
1773 ( rArg.Operation == ucb::TransferCommandOperation_MOVE ) )
1774 {
1775 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1776 xTarget, uno::UNO_QUERY );
1777 if ( !xCommandProcessor.is() )
1778 {
1779 uno::Any aProps
1780 = uno::makeAny(
1781 beans::PropertyValue(
1782 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1783 "Uri")),
1784 -1,
1785 uno::makeAny(rArg.TargetURL),
1786 beans::PropertyState_DIRECT_VALUE));
1787 ucbhelper::cancelCommandExecution(
1788 ucb::IOErrorCode_CANT_READ,
1789 uno::Sequence< uno::Any >(&aProps, 1),
1790 xEnv,
1791 rtl::OUString::createFromAscii(
1792 "Target content is not a XCommandProcessor!" ),
1793 this );
1794 // Unreachable
1795 }
1796
1797 ucb::TransferInfo aTransferArg(
1798 ( rArg.Operation
1799 == ucb::TransferCommandOperation_MOVE ), // MoveData
1800 rArg.SourceURL, // SourceURL
1801 rArg.NewTitle, // NewTitle
1802 rArg.NameClash ); // NameClash
1803
1804 bool bRetry;
1805 do
1806 {
1807 bRetry = false;
1808
1809 try
1810 {
1811 ucb::Command aCommand(
1812 rtl::OUString::createFromAscii( "transfer" ), // Name
1813 -1, // Handle
1814 uno::makeAny( aTransferArg ) ); // Argument
1815
1816 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
1817
1818 // Command succeeded. We're done.
1819 return;
1820 }
1821 catch ( ucb::InteractiveBadTransferURLException const & )
1822 {
1823 // Source URL is not supported by target. Try to transfer
1824 // the content "manually".
1825 }
1826 catch ( ucb::UnsupportedCommandException const & )
1827 {
1828 // 'transfer' command is not supported by commandprocessor.
1829 // Try to transfer manually.
1830 }
1831 catch ( ucb::UnsupportedNameClashException const & exc )
1832 {
1833 OSL_ENSURE( aTransferArg.NameClash == exc.NameClash,
1834 "nameclash mismatch!" );
1835 if ( exc.NameClash == ucb::NameClash::ASK )
1836 {
1837 // Try to detect a name clash by invoking "transfer" with
1838 // NameClash::ERROR.
1839 try
1840 {
1841 ucb::TransferInfo aTransferArg1(
1842 aTransferArg.MoveData,
1843 aTransferArg.SourceURL,
1844 aTransferArg.NewTitle,
1845 ucb::NameClash::ERROR );
1846
1847 ucb::Command aCommand1(
1848 rtl::OUString::createFromAscii( "transfer" ),
1849 -1,
1850 uno::makeAny( aTransferArg1 ) );
1851
1852 xCommandProcessor->execute( aCommand1, 0, xLocalEnv );
1853
1854 // Command succeeded. We're done.
1855 return;
1856 }
1857 catch ( ucb::UnsupportedNameClashException const & )
1858 {
1859 // No chance to solve name clashes, because I'm not
1860 // able to detect whether there is one.
1861 throw exc; // Not just 'throw;'!
1862 }
1863 catch ( ucb::NameClashException const & )
1864 {
1865 // There's a clash. Use interaction handler to solve it.
1866
1867 uno::Any aExc;
1868 rtl::OUString aNewTitle;
1869 NameClashContinuation eCont
1870 = interactiveNameClashResolve(
1871 xEnv, // always use original environment!
1872 rArg.TargetURL, // target folder URL
1873 createDesiredName(
1874 aTransferArg ), // clashing name
1875 aExc,
1876 aNewTitle );
1877
1878 switch ( eCont )
1879 {
1880 case NOT_HANDLED:
1881 // Not handled.
1882 cppu::throwException( aExc );
1883 // break;
1884
1885 case UNKNOWN:
1886 // Handled, but not clear, how...
1887 // fall-thru intended.
1888
1889 case ABORT:
1890 throw ucb::CommandFailedException(
1891 rtl::OUString(
1892 RTL_CONSTASCII_USTRINGPARAM(
1893 "abort requested via interaction "
1894 "handler" ) ),
1895 uno::Reference< uno::XInterface >(),
1896 aExc );
1897 // break;
1898
1899 case OVERWRITE:
1900 aTransferArg.NameClash
1901 = ucb::NameClash::OVERWRITE;
1902 bRetry = true;
1903 break;
1904
1905 case NEW_NAME:
1906 aTransferArg.NewTitle = aNewTitle;
1907 bRetry = true;
1908 break;
1909 }
1910
1911 OSL_ENSURE( bRetry, "bRetry must be true here!!!" );
1912 }
1913 }
1914 else
1915 {
1916 throw;
1917 }
1918 }
1919 }
1920 while ( bRetry );
1921 }
1922
1923 //////////////////////////////////////////////////////////////////////
1924 //
1925 // (2) Try to transfer the content "manually".
1926 //
1927 //////////////////////////////////////////////////////////////////////
1928
1929 uno::Reference< ucb::XContent > xSource;
1930 try
1931 {
1932 uno::Reference< ucb::XContentIdentifier > xId2
1933 = createContentIdentifier( rArg.SourceURL );
1934 if ( xId2.is() )
1935 xSource = queryContent( xId2 );
1936 }
1937 catch ( ucb::IllegalIdentifierException const & )
1938 {
1939 // Error handling via "if ( !xSource.is() )" below.
1940 }
1941
1942 if ( !xSource.is() )
1943 {
1944 uno::Any aProps
1945 = uno::makeAny(beans::PropertyValue(
1946 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1947 "Uri")),
1948 -1,
1949 uno::makeAny(rArg.SourceURL),
1950 beans::PropertyState_DIRECT_VALUE));
1951 ucbhelper::cancelCommandExecution(
1952 ucb::IOErrorCode_CANT_READ,
1953 uno::Sequence< uno::Any >(&aProps, 1),
1954 xEnv,
1955 rtl::OUString::createFromAscii(
1956 "Can't instantiate source object!" ),
1957 this );
1958 // Unreachable
1959 }
1960
1961 uno::Reference< ucb::XCommandProcessor > xCommandProcessor(
1962 xSource, uno::UNO_QUERY );
1963 if ( !xCommandProcessor.is() )
1964 {
1965 uno::Any aProps
1966 = uno::makeAny(beans::PropertyValue(
1967 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1968 "Uri")),
1969 -1,
1970 uno::makeAny(rArg.SourceURL),
1971 beans::PropertyState_DIRECT_VALUE));
1972 ucbhelper::cancelCommandExecution(
1973 ucb::IOErrorCode_CANT_READ,
1974 uno::Sequence< uno::Any >(&aProps, 1),
1975 xEnv,
1976 rtl::OUString::createFromAscii(
1977 "Source content is not a XCommandProcessor!" ),
1978 this );
1979 // Unreachable
1980 }
1981
1982 // Obtain interesting property values from source...
1983
1984 uno::Sequence< beans::Property > aProps( 4 );
1985
1986 aProps[ 0 ].Name = rtl::OUString::createFromAscii( "IsFolder" );
1987 aProps[ 0 ].Handle = -1; /* unknown */
1988 aProps[ 1 ].Name = rtl::OUString::createFromAscii( "IsDocument" );
1989 aProps[ 1 ].Handle = -1; /* unknown */
1990 aProps[ 2 ].Name = rtl::OUString::createFromAscii( "TargetURL" );
1991 aProps[ 2 ].Handle = -1; /* unknown */
1992 aProps[ 3 ].Name = rtl::OUString::createFromAscii( "BaseURI" );
1993 aProps[ 3 ].Handle = -1; /* unknown */
1994
1995 ucb::Command aGetPropsCommand(
1996 rtl::OUString::createFromAscii( "getPropertyValues" ),
1997 -1,
1998 uno::makeAny( aProps ) );
1999
2000 uno::Reference< sdbc::XRow > xRow;
2001 xCommandProcessor->execute( aGetPropsCommand, 0, xLocalEnv ) >>= xRow;
2002
2003 if ( !xRow.is() )
2004 {
2005 uno::Any aProps2
2006 = uno::makeAny(beans::PropertyValue(
2007 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
2008 "Uri")),
2009 -1,
2010 uno::makeAny(rArg.SourceURL),
2011 beans::PropertyState_DIRECT_VALUE));
2012 ucbhelper::cancelCommandExecution(
2013 ucb::IOErrorCode_CANT_READ,
2014 uno::Sequence< uno::Any >(&aProps2, 1),
2015 xEnv,
2016 rtl::OUString::createFromAscii(
2017 "Unable to get properties from source object!" ),
2018 this );
2019 // Unreachable
2020 }
2021
2022 TransferCommandContext aTransferCtx(
2023 m_xSMgr, this, xLocalEnv, xEnv, rArg );
2024
2025 if ( rArg.NewTitle.getLength() == 0 )
2026 {
2027 // BaseURI: property is optional.
2028 rtl::OUString aBaseURI( xRow->getString( 4 ) );
2029 if ( aBaseURI.getLength() )
2030 {
2031 aTransferCtx.aArg.NewTitle
2032 = createDesiredName( aBaseURI, rtl::OUString() );
2033 }
2034 }
2035
2036 // Do it!
2037 globalTransfer_( aTransferCtx, xSource, xTarget, xRow );
2038
2039 //////////////////////////////////////////////////////////////////////
2040 //
2041 // (3) Delete source, if operation is MOVE.
2042 //
2043 //////////////////////////////////////////////////////////////////////
2044
2045 if ( rArg.Operation == ucb::TransferCommandOperation_MOVE )
2046 {
2047 try
2048 {
2049 ucb::Command aCommand(
2050 rtl::OUString::createFromAscii( "delete" ), // Name
2051 -1, // Handle
2052 uno::makeAny( sal_Bool( sal_True ) ) ); // Argument
2053
2054 xCommandProcessor->execute( aCommand, 0, xLocalEnv );
2055 }
2056 catch ( uno::Exception const & )
2057 {
2058 OSL_ENSURE( sal_False, "Cannot delete source object!" );
2059 throw;
2060 }
2061 }
2062 }
2063